双向循环链表
Posted lnlin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了双向循环链表相关的知识,希望对你有一定的参考价值。
为什么使用双向循环链表?
在单链表中,查询一个结点的前驱需要从头指针出发,为克服单链表单向性的缺点,可以利用双向链表
双向链表的结点中有两个指针域,其中一个指向前驱,一个指向后继
用于测试的文件,以及测试结果可以去作者GitHub上查看
(下面代码只是最初实现,后续如果有修改,由于太麻烦,不会再更改下文,仅仅更新Github上的代码文件)
具体实现:
1 // 双向循环链表 2 // 双向链表的结点 3 class DuLNode { 4 public: 5 DuLNode() { 6 data = INITDLNODE; 7 prior = nullptr; 8 next = nullptr; 9 } 10 11 DuLNode(ElemType ele, DuLNode *p, DuLNode *n) : data(ele), prior(p), next(n) { 12 13 } 14 15 ElemType data; 16 DuLNode *prior; // 指向前驱结点 17 DuLNode *next; // 指向后继结点 18 }; 19 20 class DoubleLinkedList { 21 public: 22 DoubleLinkedList(); 23 DoubleLinkedList(int len); 24 ~DoubleLinkedList(); 25 26 DuLNode *DoubleLinkedListHead() { 27 return head; 28 } 29 30 DuLNode *CListHead() { 31 return head; 32 } 33 34 // 获取链表长度 35 int DListLength(); 36 37 // 判断链表是否为空 38 bool DListEmpty(); 39 40 // 返回链表中第pos个结点 41 bool GetNode(int pos, DuLNode **node); 42 43 // 返回指定data在链表中第一次出现的位置 44 bool LocateNode(ElemType ele, DuLNode **node); 45 46 // 在指定位置插入后一个结点,但若pos为0是表示在链表头插入一个结点 47 bool DListInsert(int pos, DuLNode *node); 48 49 // 删除指定位置结点 50 bool DListDelete(int pos); 51 52 // 删除指定位置结点并返回被删除结点的信息 53 bool DListDelete(int pos, DuLNode *node); 54 55 // 遍历线性表 56 void DListTraverse(); 57 58 // 在链表尾添加cnt个结点 59 bool DListAddNodes(int cnt); 60 61 // 销毁链表,释放所有结点资源 62 void DListDestory(); 63 64 // 查询某个节点是否在此链表中 65 bool DListNodeIsInList(DuLNode *node); 66 67 // 查询某个节点是否在此链表中,并返回其位置所在 68 bool DListNodeIsInList(DuLNode *node, int *pos); 69 70 private: 71 DuLNode *head; 72 // head作为双向循环链表的头结点,但其仅仅作为一个标志作用,该节点无数据域(其数据域数据无意义),且仅用于链表操作,并不作为逻辑上的链表节点 73 // 逻辑上链表第一个结点为head指向的下一个结点 74 }; 75 76 /* 77 注意: 78 在上述实现中: 79 链表头结点,不储存数据,在测试链表是否为空、计算链表长度时不包括该结点 80 作为一个标志作用,该节点无数据域(其数据域数据无意义) 81 在使用链表时注意此时操作的结点是否为head 82 但在考虑链表中结点的前驱和后继时,head是第一个结点的前驱,最后一个结点的后继 83 */
1 DoubleLinkedList::DoubleLinkedList() 2 { 3 head = new DuLNode; 4 head->prior = head; 5 head->next = head; 6 } 7 8 DoubleLinkedList::DoubleLinkedList(int len) 9 { 10 head = new DuLNode; 11 head->prior = head; 12 head->next = head; 13 14 DListAddNodes(len); 15 } 16 17 DoubleLinkedList::~DoubleLinkedList() 18 { 19 DListDestory(); 20 delete head; 21 } 22 23 bool DoubleLinkedList::DListEmpty() 24 { 25 return (head == head->next) ? true : false; 26 } 27 28 29 int DoubleLinkedList::DListLength() 30 { 31 DuLNode *temp = head; 32 int cnt = 0; 33 34 while (head != temp->next) { 35 cnt++; 36 temp = temp->next; 37 } 38 39 return cnt; 40 } 41 42 43 bool DoubleLinkedList::GetNode(int pos, DuLNode **node) 44 { 45 if (pos > DListLength() || pos < 1) 46 return false; 47 48 DuLNode *cur = head; 49 50 for (int i = 1; i <= pos; i++) { 51 cur = cur->next; 52 } 53 54 *node = cur; 55 56 return true; 57 } 58 59 60 bool DoubleLinkedList::LocateNode(ElemType ele, DuLNode **node) 61 { 62 DuLNode *curNode = head; 63 64 while (head != curNode->next) { 65 if (curNode->data == ele) { 66 *node = curNode; 67 return true; 68 } 69 70 curNode = curNode->next; 71 } 72 *node = nullptr; 73 74 return false; 75 } 76 77 78 bool DoubleLinkedList::DListInsert(int pos, DuLNode *node) 79 { 80 // 插入位置错误 81 if (pos < 0 || pos > DListLength()) 82 return false; 83 84 if (pos == 0) { 85 node->next = head->next; 86 node->prior = head; 87 head->next = node; 88 } 89 else { 90 DuLNode *temp = nullptr; 91 this->GetNode(pos, &temp); 92 node->next = temp->next; 93 node->prior = temp; 94 temp->next = node; 95 } 96 97 return true; 98 } 99 100 bool DoubleLinkedList::DListDelete(int pos) 101 { 102 if (pos <1 || pos > DListLength()) 103 return false; 104 105 // 由于每个结点可以获取其前驱结点信息,相对于单向循环链表的实现,下面实现更为简单 106 DuLNode *del; 107 GetNode(pos, &del); 108 del->prior->next = del->next; 109 del->next->prior = del->prior; 110 delete(del); 111 112 return true; 113 } 114 115 116 bool DoubleLinkedList::DListDelete(int pos, DuLNode *node) 117 { 118 if (pos <1 || pos > DListLength()) 119 return false; 120 121 // 由于每个结点可以获取其前驱结点信息,相对于单向循环链表的实现,下面实现更为简单 122 DuLNode *del; 123 GetNode(pos, &del); 124 125 del->prior->next = del->next; 126 del->next->prior = del->prior; 127 // 返回所需数据 128 node->data = del->data; 129 node->prior = del->prior; 130 node->next = del->next; 131 delete(del); 132 133 return true; 134 } 135 136 137 void DoubleLinkedList::DListTraverse() 138 { 139 DuLNode *curNode = head->next; 140 141 while (curNode != head) { 142 std::cout << curNode->data << std::endl; 143 curNode = curNode->next; 144 } 145 } 146 147 148 bool DoubleLinkedList::DListAddNodes(int cnt) 149 { 150 if (cnt < 0) 151 return false; 152 else if (cnt == 0) 153 return true; 154 155 DuLNode *lastNode = head->prior; // 获取最后一个结点 156 157 for (int i = 0; i < cnt; i++) { 158 ElemType temp; 159 std::cin >> temp; 160 DuLNode *node = new DuLNode(temp, nullptr, nullptr); 161 162 if (!node) { 163 return false; 164 } 165 166 lastNode->next = node; 167 node->prior = lastNode; 168 node->next = head; 169 lastNode = node; 170 } 171 172 return true; 173 } 174 175 176 void DoubleLinkedList::DListDestory() 177 { 178 DuLNode *cur = head->next; 179 DuLNode *next = cur->next; 180 181 while (head != cur) { 182 delete cur; 183 cur = next; 184 next = next->next; 185 } 186 } 187 188 bool DoubleLinkedList::DListNodeIsInList(DuLNode *node) 189 { 190 DuLNode *cur = head->next; 191 192 while (cur != head) { 193 if (cur == node) { 194 return true; 195 } 196 197 cur = cur->next; 198 } 199 200 return false; 201 } 202 203 bool DoubleLinkedList::DListNodeIsInList(DuLNode *node, int *pos) 204 { 205 DuLNode *cur = head->next; 206 int cnt = 0; 207 208 while (cur != head) { 209 cnt++; 210 211 if (cur == node) { 212 *pos = cnt; 213 return true; 214 } 215 216 cur = cur->next; 217 } 218 219 return false; 220 }
以上是关于双向循环链表的主要内容,如果未能解决你的问题,请参考以下文章