线性表->链式存储->双向链表

文字描述

  之前的链表(单链表、循环链表)的链式存储结构中只有一个指示直接后继的指针域。由此,从某个结点出发只能顺指针往后寻查其他结点。若要寻查结点的直接前驱,则需从表头指针出发。即单链表中,NextElem的执行时间为1,而PriorElem的执行时间为n。为了克服单链表这种缺点,可利用双向链表。

  在双向链表中,每个节点有两个指针域,一个指向其直接后继,一个指向其直接前驱。

示意图

算法分析

插入、删除、查找、求后继等同单链表。但是求前驱不一样,其时间复杂度为1。

代码实现

  1 //
  2 // Created by lady on 19-1-31.
  3 //
  4 
  5 #include <stdlib.h>
  6 #include <stdio.h>
  7 #include <string.h>
  8 
  9 //线性表的双向循环链表存储结构
 10 typedef struct ElemType{
 11     char data[10];
 12 }ElemType;
 13 typedef struct DuLNode{
 14     ElemType e;
 15     struct DuLNode *prior;
 16     struct DuLNode *next;
 17 }DuLNode, *DuLinkList;
 18 
 19 //构造一个空的双向循环链表
 20 static int InitList_DuL(DuLinkList *L)
 21 {
 22     (*L) = (DuLinkList)malloc(sizeof(DuLNode));
 23     (*L)->prior = (*L);
 24     (*L)->next = (*L);
 25     memset((*L)->e.data, 0, sizeof((*L)->e.data));
 26     return 0;
 27 }
 28 
 29 //销毁L
 30 static int Destory_DuL(DuLinkList *L)
 31 {
 32     DuLNode *p = NULL;
 33     DuLNode *q = NULL;
 34     p = (*L)->next;
 35     while(p){
 36         q = p;
 37         p = p->next;
 38         free(q);
 39         if(p == (*L))
 40             break;
 41     }
 42     free(*L);
 43     (*L) = NULL;
 44     return 0;
 45 }
 46 
 47 //返回双向链表L中的第i个位置的元素
 48 static DuLNode *GetElemP_DuL(DuLinkList *L, int i)
 49 {
 50     if(L == NULL){
 51         return NULL;
 52     }
 53     DuLNode *p = (*L)->next;
 54     int index = 1;
 55     while(index<i && p){
 56         index += 1;
 57         p = p->next;
 58     }
 59     if(index == i && p){
 60         return p;
 61     }else{
 62         return NULL;
 63     }
 64 }
 65 
 66 //在L的指定位置i的元素前面插入元素e
 67 static int ListInsert_DuL(DuLinkList *L, int i, ElemType e)
 68 {
 69     DuLNode *p = NULL;
 70     DuLNode *new = NULL;
 71     if((p=GetElemP_DuL(L, i)) == NULL){
 72         return -1;
 73     }
 74     if((new = (DuLNode*)malloc(sizeof(DuLNode))) == NULL){
 75         return -1;
 76     }
 77     new->e = e;
 78     new->prior = p->prior;
 79     p->prior->next = new;
 80     new->next = p;
 81     p->prior = new;
 82     return 0;
 83 }
 84 
 85 //删除L中的第loc个数据元素,并将被删元素的值存放在e中
 86 static int ListDelete_DuL(DuLinkList *L, int i, ElemType *e)
 87 {
 88     DuLNode *p = NULL;
 89     if((p=GetElemP_DuL(L, i)) == NULL){
 90         return -1;
 91     }
 92     (*e) = p->e;
 93     p->prior->next = p->next;
 94     p->next->prior = p->prior;
 95     free(p);
 96     return 0;
 97 }
 98 
 99 //依次对L的每个数据元素调用函数fun
100 static int listTraverse_DuL(DuLinkList *L, int (*fun)(ElemType,int), char note[])
101 {
102     printf("遍历双向循环链表%s:", note);
103     DuLNode *p = NULL;
104     p = (*L)->next;
105     int i = 1;
106     while(p){
107         fun(p->e, i);
108         i+=1;
109         p = p->next;
110         if(p == (*L))
111             break;
112     }
113     printf("
");
114     return 0;
115 }
116 
117 static int print(ElemType e, int loc)
118 {
119     printf("%3d=%-10s", loc, e.data);
120 }
121 
122 //创建一个长度为n的双向链表
123 static int CreateList_DuL(DuLinkList *L, int n, char note[])
124 {
125     printf("创建一个长度为%d的双向循环链表%s!
", n, note);
126     InitList_DuL(L);
127     ElemType e;
128     int i = 0;
129     for(i=0; i<n; i++){
130         printf("输入第%d个元素:", i+1);
131         scanf("%s[^\n]", e.data);
132         ListInsert_DuL(L, i+1, e);
133     }
134     return 0;
135 }
136 
137 int main(int argc, char *argv[])
138 {
139     ElemType e;
140     DuLinkList L;
141     int location=0;
142 
143     CreateList_DuL(&L, 5, "L");
144 
145     listTraverse_DuL(&L, print, "L");
146 
147 
148     printf("输入插入元素的位置:");
149     scanf("%d", &location);
150     printf("输入插入元素的数据:");
151     scanf("%s[^\n]", e.data);
152     ListInsert_DuL(&L, location, e);
153     listTraverse_DuL(&L, print, "L");
154 
155     printf("输入删除元素的位置:");
156     scanf("%d", &location);
157     ListDelete_DuL(&L, location, &e);
158 
159     printf("位于%d的元素%s已经从双向循环链表中被删除!
", location, e.data);
160     listTraverse_DuL(&L, print, "L");
161 
162     Destory_DuL(&L);
163     printf("双向链表已经被销毁!
");
164     return 0;
165 }
双向链表

代码运行

/home/lady/CLionProjects/untitled/cmake-build-debug/untitled
创建一个长度为5的双向循环链表L!
输入第1个元素:c
输入第2个元素:b
输入第3个元素:e
输入第4个元素:g
输入第5个元素:f
遍历双向循环链表L:  1=c           2=b           3=e           4=g           5=f         
输入插入元素的位置:3
输入插入元素的数据:test
遍历双向循环链表L:  1=c           2=b           3=test        4=e           5=g           6=f         
输入删除元素的位置:4
位于4的元素e已经从双向循环链表中被删除!
遍历双向循环链表L:  1=c           2=b           3=test        4=g           5=f         
双向链表已经被销毁!

Process finished with exit code 0
原文地址:https://www.cnblogs.com/aimmiao/p/10392258.html