双向链表主要为了解决单链表找前驱的问题。除了插入、删除操作之外,其他操作与单链表都相同。因此这里只是比较简单的写了双向链表的插入和删除操作。画出结点结构图的话,思路会很清晰,线性表这块还算是比较简单的能够实现。
1 /* 2 在单链表中,求后继的方法NextElem执行的时间为O(1),求前驱的方法PriorElem执行的时间为O(n), 3 引入双向链表就是为了克服单链表这种单向性的缺点。 4 */ 5 6 #include<stdio.h> 7 #include<stdlib.h> 8 9 //定义存储类型 10 typedef int ElemType; 11 12 //双向链表的存储结构 13 typedef struct DuLNode{ 14 ElemType data; 15 DuLNode *next; 16 DuLNode *prior; 17 }DuLNode, *DuLinkList; 18 19 //声明,指针函数 20 void(*visit)(DuLNode *node); 21 22 //声明,辅助函数 23 void visitData(DuLNode *node); 24 25 //对双向链表的基本操作 26 bool InitDuLinkList(DuLinkList &L); // 初始化一个空表 27 DuLinkList GetLNode(DuLinkList L, int i); //返回第i个结点 28 void ListTraverse(DuLinkList L, void(visit(DuLNode *node))); //遍历双向链表 29 void ListInsert(DuLinkList &L, int i, ElemType e); //在第i个结点之前插入,数据域是e的结点 30 void AppendLast(DuLinkList &L, ElemType e); //在最后一个结点之后插入,数据域是e的结点 31 void ListDelete(DuLinkList &L, int i, DuLinkList &rNode); //删除第i个结点并返回 32 33 //测试模块 34 int main(){ 35 36 DuLinkList L; 37 InitDuLinkList(L); 38 for (int i = 1; i <= 6; i++) 39 AppendLast(L, i); 40 ListTraverse(L, visitData); 41 printf("\n"); 42 43 printf("第一个元素的后继是:%d\n", GetLNode(L, 1)->next->data); 44 printf("第一个元素的前驱是:%d\n", GetLNode(L, 1)->prior->data); 45 printf("最后一个元素的前驱是:%d\n", GetLNode(L, 6)->prior->data); 46 printf("\n"); 47 48 ListInsert(L, 1, 7); 49 ListTraverse(L, visitData); 50 printf("第一个元素的后继是:%d\n", GetLNode(L, 1)->next->data); 51 printf("第一个元素的前驱是:%d\n\n", GetLNode(L, 1)->prior->data); 52 53 DuLNode *rNode; 54 ListDelete(L, 7, rNode); 55 ListTraverse(L, visitData); 56 printf("最后一个元素的前驱是:%d\n", GetLNode(L, 6)->prior->data); 57 ListDelete(L, 1, rNode); 58 ListTraverse(L, visitData); 59 printf("第一个元素的后继是:%d\n", GetLNode(L, 1)->next->data); 60 printf("第一个元素的前驱是:%d\n\n", GetLNode(L, 1)->prior->data); 61 62 system("pause"); 63 return 0; 64 } 65 66 //各函数定义模块 67 void visitData(DuLNode *node){ 68 printf("%4d", node->data); 69 } 70 71 bool InitDuLinkList(DuLinkList &L){ // 初始化一个空表 72 L = (DuLinkList)malloc(sizeof(DuLNode)); 73 if (!L) 74 return false; 75 L->prior = NULL; 76 L->next = NULL; 77 return true; 78 } 79 80 DuLinkList GetLNode(DuLinkList L, int i){ //返回第i个结点的值 81 int j = 1; 82 DuLNode *p = L->next; 83 84 //找第i个结点 85 while (p && j != i){ 86 p = p->next; 87 j++; 88 } 89 90 if (j > i || !p){ 91 printf("\n不存在该结点!\n"); 92 return L; 93 } 94 95 return p; 96 } 97 98 void ListTraverse(DuLinkList L, void(visit(DuLNode *node))){ //遍历单链表 99 DuLNode *p = L->next; 100 while (p){ 101 visit(p); 102 p = p->next; 103 } 104 printf("\n"); 105 } 106 107 void ListInsert(DuLinkList &L, int i, ElemType e){ //在第i个结点之前插入,数据域是e的结点 108 DuLNode *p = GetLNode(L, i); 109 if (!p){ 110 printf("没找到该元素,不能进行插入!\n"); 111 return; 112 } 113 114 DuLNode *s = (DuLinkList)malloc(sizeof(DuLNode)); 115 if (!s) 116 return; 117 s->data = e; 118 s->next = p; 119 p->prior->next = s; 120 s->prior = p->prior; 121 p->prior = s; 122 } 123 124 void AppendLast(DuLinkList &L, ElemType e){ //在最后一个结点之后插入,数据域是e的结点 125 //找到最后一个结点 126 DuLNode *p = L; 127 while (p->next){ 128 p = p->next; 129 } 130 //新建一个结点 131 DuLNode *newNode = (DuLinkList)malloc(sizeof(DuLNode)); 132 if (!newNode) 133 return; 134 newNode->data = e; 135 //插入 136 newNode->next = p->next; 137 p->next = newNode; 138 newNode->prior = p; 139 } 140 141 void ListDelete(DuLinkList &L, int i, DuLinkList &rNode){ //删除第i个结点并返回 142 DuLNode *p = GetLNode(L, i); 143 if (!p){ 144 printf("没找到该元素,不能进行删除!\n"); 145 return; 146 } 147 148 p->prior->next = p->next; 149 if (p->next){ 150 p->next->prior = p->prior; 151 p->next = NULL; 152 p->prior = NULL; 153 } 154 155 rNode = p; 156 free(p); 157 }
不积跬步,无以至千里;不积小流,无以成江海。坚持着。
时间: 2024-10-21 20:32:16