线性表的链式存储方式:
线性表的链式存储就是用一组地址任意的存储单元存放线性表的数据元素
- 单链表
以元素(数据元素的映象) + 指针(指示后继元素存储位置) =结点
以“结点的序列”表示线性表称作单链表
以线性表中第一个数据元素的存储地址作为线性表的地址,称作线性表的头指针
有时为了操作方便,在第一个结点之前虚加一个“头结点”,以指向头结点的指针为链表的头指针。
1 Typedef struct LNode {3 ElemType data; // 数据域 5 struct Lnode *next; // 指针域 7 } LNode, *LinkList 9 LinkList L; // L 为单链表的头指针
算法1. 获取
1 Status GetElem_L(LinkList L, int i, ElemType &e) // L是带头结点的链表的头指针,以 e 返回第 i 个元素 3 { p = L->next; j = 1; // p指向第一个结点,j为计数器 5 while (p && j next; ++j; } // 顺指针向后查找,直到 p 指向第 i 个元素或 p 为空 7 if ( !p || j>i ) 9 return ERROR; // 第 i 个元素不存在 11 e = p->data; // 取得第 i 个元素 13 return OK; 15 } // GetElem_L 17 算法时间复杂度为O(ListLength(L))
算法2. 插入
1 Status ListInsert (LinkList &L, int i, ElemType e) 3 { // 在链表中第i 个结点之前插入新的元素 e 5 p = L; j = 0; // j为计数器 7 while (p && jnext; ++j; } // 顺指针向后查找,直到p指向第i-1个元素或p为空 11 if ( !p || j>i-1 ) return ERROR; 13 s = (LinkList) malloc ( sizeof (LNode)); // 生成新结点 15 s->data = e; 17 s->next = p->next; 19 p->next = s; // 插入 21 return OK; 23 }
算法3 . 删除
1 Status ListDelete_L(LinkList L, int i, ElemType &e) 3 { // 删除以 L 为头指针(带头结点)的单链表中第 i 个结点 5 p = L; j = 0; 7 while (p->next && j < i-1) { p = p->next; ++j; } // 寻找第 i 个结点并令 p 指向其前趋 9 if (!(p->next) || j > i-1) return ERROR; // 删除位置不合理 11 q = p->next; 13 p->next = q->next; 15 e = q->data; 17 free(q); // 删除并释放结点 19 return OK; 21 } // ListDelete_L
算法4 置空表操作 ClearList(&L) 在链表中的实现:
1 void ClearList(&L) { // 将单链表重新置为一个空表 3 while (L->next) 5 { p=L->next; 7 L->next=p->next; 9 free(p); } 11 } // ClearList 13 注意:插入的算法p->next = L->next; L->next = p;
算法5 合并
1 Status MergeList (LinkList &La, LinkList &Lb, LinkList &Lc) 3 { 5 pa = La ->next; pb = Lb ->next; 7 Lc=pc = La; 9 while (pa && pb) { 11 if (pa->data<= pb->data) 13 {pc->next =pa; 15 pc=pa; 17 pa= pa->next; 19 } 21 else{ 23 pc->next=pb; 25 pc=pb; 27 pb= pb->next; 29 } 31 } 33 pc->next =pa?pb:pb; 35 free(Lb); 37 }
2. 双向链表
1 typedef struct DuLNode {3 ElemType data; // 数据域 5 struct DuLNode *prior; // 指向前驱的指针域 7 struct DuLNode *next; // 指向后继的指针域 9 } DuLNode, *DuLinkList;
3. 循环链表
最后一个结点的指针域的指针又指回第一个结点的链表
和单链表的差别仅在于,判别链表中最后一个结点的条件不再是“后继是否为空”,而是“后继是否为头结点”。
4 双向循环链表
插入
1 s->prior = p->prior; 3 p->prior->next = s; 5 s->next = p; 7 p ->prior = s;
在ai-1与ai之间插入节点为指针s,其中p指针指向ai
注意:也可以这样理解,=之前的指针指向=之后的指针
删除
1 q= p->next;2 e=q->data3 p->next = q->next; 4 p->next->prior = p; 5 free(q);
在ai-1与ai+1之间删除节点为指针ai,其中p指针指向ai-1,其中q指针指向ai
总结链式存储结构的优缺点:
1.单链表的优点
(1)插入、删除操作方便
(2)不需预先分配空间 它是一种动态结构,整个存储空间为多个链表共用
2.单链表的缺点
(1)指针占用额外存储空间
(2)不能随机存取,查找速度慢
建表过程:
p->next = L->next;
L->next = p