zoukankan      html  css  js  c++  java
  • 双向循环链表

    为什么使用双向循环链表?

    在单链表中,查询一个结点的前驱需要从头指针出发,为克服单链表单向性的缺点,可以利用双向链表
    双向链表的结点中有两个指针域,其中一个指向前驱,一个指向后继

    用于测试的文件,以及测试结果可以去作者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 }
  • 相关阅读:
    maven dependencies 里面的包怎么导出
    webUploader react 接口设计
    HTML5 History API实现无刷新跳转
    Object.defineproperty实现数据和视图的联动
    jsLoader、cssLoader、imageLoader
    【转】前端工程化-公共模块的依赖和常用的工作流
    JDBC详解
    正则表达式
    【GOF23设计模式】备忘录模式
    【GOF23设计模式】观察者模式
  • 原文地址:https://www.cnblogs.com/lnlin/p/10872983.html
Copyright © 2011-2022 走看看