2.线性链表
线性链表是由n个结点链结成的一个链表。结点包括两个域:存储数据元素信息的域称为数据域;存储直接后继存储位置的域称为指针域。指针域中存储的信息称为指针或链。数据元素之间的逻辑关系是由结点中的指针指示的。
单链表可由头指针唯一确定,头指针指示链表中第一个结点的存储位置。
//----------------线性表的单链表存储结构----------------
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode, * LinkList;
单链表的第一个结点之前附设一个结点,称为头结点。头结点的数据域可以不存储任何信息,也可以存储如线性表的长度等类的附加信息,头结点的指针域存储指向第一个结点的指针(即第一个元素结点的存储位置)。若线性表为空表,则头结点的指针域为空。
//----------------L为带头结点的单链表的头指针----------------
//----------------当第i个元素存在时,其值赋给e并返回----------------
Status GetElem_L(LinkList L, int i, ElemType &e){
LNode *p = L->next; //初始化,p指向第一个结点
j = 1;
while (p && j < i){
p = p->next;
++j;
}
if (!p || j > i)
return ERROR;
e = p->data;
return OK;
}
插入操作的指针修改语句为:
s -> next = p -> next; p -> next = s;
删除操作的描述语句为:
p - > next = p -> next -> next;
//----------------带头结点的单链表L中第i个位置之前插入元素e----------------
Status ListInsert_L(LinkList &L, int i, ElemType e){
LNode *p = L;
j = 0;
while (p && j < i - 1){
p = p -> next;
++j;
}
if (!p || j > i - 1)
return ERROR;
LNode *s = (LinkList)malloc(sizeof (LNode));
s ->data = e;
s ->next = p ->next;
p ->next = s;
return OK;
}
//----------------带头结点的单链表L中,删除第i个位置元素,并由e返回其值----------------
Status ListDelete_L(LinkList &L, int i, ElemType &e){
LNode *p = L;
j = 0;
while (p ->next && j < i - 1){
p = p ->next;
++j;
}
if (! p ->next || j > i - 1)
return ERROR;
LNode *q = p ->next;
p ->next = q ->next;
e = q ->data;
free (q);
return OK;
}
两个算法的时间复杂度都是O(n)。单链表和顺序存储结构不同,它是一种动态结构。建立线性表的链式存储结构的过程就是一个动态生成链表的过程。
//----------------逆位序输入n个元素的值,建立带头结点的单链表L----------------
void CreateList_L(LinkList &L, int n){
L = (LinkList) malloc (sizeof (LNode));
L ->next = NULL; //先建立一个带头结点的单链表
LNode *p;
for (int i = n; i > 0; --i){
p = (LinkList) malloc (sizeof (LNode));
scanf (&p ->data);
p ->next = L ->next;
L ->next = p;
}
return OK;
}
逆序建立单链表算法的时间复杂度都是O(n)。
//----------------已知单链线性表La和Lb的元素按值非递减排列----------------
//----------------归并La和Lb得到新的单链线性表Lc,Lc的元素也按照非递减排列----------------
void MergeList_L(LinkList &La, LinkList &Lb, LinkList &Lc){
LNode *pa = La ->next;
LNode *pb = Lb ->next;
LNode *pc;
Lc = pc = La; //用La的头结点作为Lc的头结点
while (pa && pb){
if (pa ->data <= pb ->data){
pc ->next = pa;
pc = pa;
pa = pa ->next;
}
else{
pc ->next = pb;
pc = pb;
pb = pb ->next;
}
}
pc ->next = pa ? pa : pb;
free (Lb); //释放Lb的头结点
}
链表归并和顺序表归并的时间复杂度相同,但空间复杂度不同。在归并两个链表为一个链表的时候,不需要另建新表的结点空间。
有时,也可借用一维数组来描述线性链表,这种描述方法便于在不设“指针”的高级程序设计语言中使用链表结构。这种用数组描述的链表称为静态链表。
//----------------线性表的静态单链表存储结构----------------
#define MAXSIZE 1000
typedef struct{
ElemType data;
int cur;
}component, SLinkList[MAXSIZE];
http://download.youkuaiyun.com/source/2179322