线性表的链式存储方式(C)
线性结构是一种基本的数据结构,主要用于对具有单一前驱和后继的数据关系进行描述。它的特点是数据元素之间呈现一种线性关系,即是元素”一个接一个排列“。
线性表
线性表是最简单、基本和常用的一种线性结构。
一个线性表是n个元素的有限序列,通常表示为(a1, a2, ... , an),非空线性表的特点如下:
- 存在唯一的一个”第一个“的元素。
- 存在唯一的一个”最后一个“的元素。
- 除第一个元素外,序列中的每个元素均只有一个直接前驱。
- 除最后一个元素外,序列中的每个元素均只有一个直接后继。
链式存储
线性表的链式存储是通过指针链接起来的结点来存储数据元素,基本的结点结构如下所示:
数据域 | 指针域 |
存储各元素的结点地址并不要求是连续的,因此存储数据元素的同时必须存储元素之间的逻辑关系。同时,结点空间只有在需要的时候才申请,无须事先分配(顺序存储必须事先分配好空间大小)。
根据结点的指针域的设置方式,还有其他的几种链表结构。
- 双向链表。每个结点包含两个指针:一个指向前驱,一个指向后继。其特点是从表中任意的结点出发,都可以从两个方向遍历链表。
- 循环链表。在单向链表(或双向链表)的基础上增加了表尾的指针指向链表的第一个结点,构成循环链表。其特点是从表中任意结点都可以遍历链表。
- 静态链表。借助数组来描述线性表的链式存储结构,用数组元素的下标表示元素所在结点的指针。
C语言实现的单链表
#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;
}
}