线性结构是一种基本的数据结构,主要用于对具有单一前驱和后继的数据关系进行描述。它的特点是数据元素之间呈现一种线性关系,即是元素”一个接一个排列“。
线性表是最简单、基本和常用的一种线性结构。
一个线性表是n个元素的有限序列,通常表示为(a1, a2, ... , an),非空线性表的特点如下:
线性表的顺序存储是指用一组地址连续的存储单元依次存储线性表中的数据元素,从而使得逻辑上相邻的两个元素在物理位置上也相邻。
#define TRUE 1 #define FALSE 0 #define ERROR -1 #define NULL -2 #define MAXSIZE 100 typedef int bool; typedef int ElementType; typedef int Position; typedef struct LNode *List; List MakeEmpty(); Position Find(List L, ElementType X); bool Insert(List L, ElementType X, Position P); bool Delete(List L, Position P); /******************************************/ /*********** 线性表的顺序存储实现 ***********/ /******************************************/ struct LNode { ElementType Data[MAXSIZE]; Position Last; }; /* 初始化 */ List MakeEmpty() { List L; L = (List)malloc(sizeof(struct LNode)); L->Last = -1; return L; } /* 查找 */ Position Find( List L, ElementType X ) { Position i = 0; while( i <= L->Last && L->Data[i]!= X ) i++; if ( i > L->Last ) return ERROR; /* 如果没找到,返回错误信息 */ else return i; /* 找到后返回的是存储位置 */ } /* 插入 */ bool Insert( List L, ElementType X, Position P ) { /* 在L的指定位置P前插入一个新元素X */ Position i; if ( L->Last == MAXSIZE-1) { /* 表空间已满,不能插入 */ printf("表满"); return FALSE; } if ( P<0 || P>L->Last+1 ) { /* 检查插入位置的合法性 */ printf("位置不合法"); return TRUE; } for( i=L->Last; i>=P; i-- ) L->Data[i+1] = L->Data[i]; /* 将位置P及以后的元素顺序向后移动 */ L->Data[P] = X; /* 新元素插入 */ L->Last++; /* Last仍指向最后元素 */ return TRUE; } /* 删除 */ bool Delete(List L, Position P) { /* 从L中删除指定位置P的元素 */ Position i; if( P<0 || P>L->Last ) { /* 检查空表及删除位置的合法性 */ printf("位置%d不存在元素", P ); return FALSE; } for( i=P+1; i<=L->Last; i++ ) L->Data[i-1] = L->Data[i]; /* 将位置P+1及以后的元素顺序向前移动 */ L->Last--; /* Last仍指向最后元素 */ return TRUE; }
线性表的链式存储是通过指针链接起来的结点来存储数据元素,基本的结点结构如下所示:
数据域 | 指针域 |
存储各元素的结点地址并不要求是连续的,因此存储数据元素的同时必须存储元素之间的逻辑关系。同时,结点空间只有在需要的时候才申请,无须事先分配(顺序存储必须事先分配好空间大小)。
#define TRUE 1 #define FALSE 0 #define ERROR -1 #define NULL -2 #define MAXSIZE 100 typedef int bool; typedef int ElementType; typedef int Position; typedef struct LNode *List; List MakeEmpty(); Position Find(List L, ElementType X); bool Insert(List L, ElementType X, Position P); bool Delete(List L, Position P); /******************************************/ /*********** 线性表的链式存储实现 ***********/ /******************************************/ typedef struct LNode *PtrToLNode; struct LNode { ElementType Data; PtrToLNode Next; }; typedef PtrToLNode Position; typedef PtrToLNode List; /* 查找 */ Position Find( List L, ElementType X ) { Position p = L; /* p指向L的第1个结点 */ while ( p && p->Data!=X ) p = p->Next; /* 下列语句可以用 return p; 替换 */ if ( p ) return p; else return ERROR; } /* 带头结点的插入 */ bool Insert( List L, ElementType X, Position P ) { /* 这里默认L有头结点 */ Position tmp, pre; /* 查找P的前一个结点 */ for ( pre=L; pre&&pre->Next!=P; pre=pre->Next ) ; if ( pre==NULL ) { /* P所指的结点不在L中 */ printf("插入位置参数错误\n"); return false; } else { /* 找到了P的前一个结点pre */ /* 在P前插入新结点 */ tmp = (Position)malloc(sizeof(struct LNode)); /* 申请、填装结点 */ tmp->Data = X; tmp->Next = P; pre->Next = tmp; return true; } } /* 带头结点的删除 */ bool Delete( List L, Position P ) { /* 这里默认L有头结点 */ Position tmp, pre; /* 查找P的前一个结点 */ for ( pre=L; pre&&pre->Next!=P; pre=pre->Next ) ; if ( pre==NULL || P==NULL) { /* P所指的结点不在L中 */ printf("删除位置参数错误\n"); return false; } else { /* 找到了P的前一个结点pre */ /* 将P位置的结点删除 */ pre->Next = P->Next; free(P); return true; } }
根据结点的指针域的设置方式,还有其他的几种链表结构。