当前位置:   article > 正文

数据结构(C++版)_数据结构c++版

数据结构c++版

数据结构学习视频:数据结构-单链表_哔哩哔哩_bilibili

参考代码(C语言):数据结构系列2-单链表 | tyrantlucifer

 

单链表

单链表是一种基础且重要的数据结构,它属于链式存储结构,用于存储线性表中的数据元素。在单链表中,数据不是以连续的内存空间形式存储,而是通过“节点”相互链接起来。

单链表的每个节点由两个部分组成:

  1. 数据域:用于存储实际的数据元素。
  2. 指针域(或称为链接域):用于存储指向下一个节点地址的指针。

从逻辑结构上看,单链表中的节点按照一定的逻辑顺序链接在一起,形成一个线性序列。第一个节点通常被称为头节点,它的指针域指向第二个节点;后续每个节点的指针域都指向其后继节点,直到最后一个节点,它的指针域指向 NULL 或者 nullptr(在不同的编程语言中可能有不同的表示方式),表示链表的结束。

单链表的主要特点包括:

  • 插入和删除操作相对数组更灵活,因为不需要移动元素,只需更改相关节点的指针即可。
  • 访问链表中的元素需要从头节点开始遍历,不能像数组那样随机访问。
  • 单链表不预先分配存储空间,可以根据需要动态地增加或减少节点,适合于无法预知数据规模的情况。
  1. #include <iostream>
  2. #define TRUE 1
  3. #define FALSE 0
  4. /**
  5. * Define the struct of list node
  6. */
  7. struct Node {
  8. int data;
  9. Node* next;
  10. };
  11. /**
  12. * Initialize a linked list
  13. * @return the head pointer of the linked list's head
  14. */
  15. Node* initList() {
  16. Node* L = new Node;
  17. L->data = 0;
  18. L->next = nullptr;
  19. return L;
  20. }
  21. /**
  22. * Insert an item at the head of the linked list
  23. * @param L the head pointer of the linked list
  24. * @param data the data you want to insert
  25. */
  26. void headInsert(Node* L, int data) {
  27. Node* node = new Node;
  28. node->data = data;
  29. node->next = L->next;
  30. L->next = node;
  31. L->data++;
  32. }
  33. /**
  34. * Insert an item at the tail of the linked list
  35. * @param L the head pointer of the linked list
  36. * @param data the data you want to insert
  37. */
  38. void tailInsert(Node* L, int data) {
  39. Node* node = L;
  40. // 遍历整个链表
  41. for (int i = 0; i < L->data; i++) {
  42. node = node->next; // 得到尾节点
  43. }
  44. Node* n = new Node;
  45. n->data = data;
  46. n->next = nullptr;
  47. node->next = n;
  48. L->data++;
  49. }
  50. /**
  51. * Delete an item from the linked list
  52. * @param L the head pointer of the linked list
  53. * @param data the data you want to delete
  54. * @return success flag
  55. */
  56. int deleteNode(Node* L, int data) {
  57. Node* preNode = L;
  58. Node* node = L->next;
  59. while (node) {
  60. if (node->data == data) {
  61. preNode->next = node->next;
  62. delete node;
  63. L->data--;
  64. return TRUE;
  65. }
  66. preNode = node;
  67. node = node->next;
  68. }
  69. return FALSE;
  70. }
  71. /**
  72. * Print all items in a linked list
  73. * @param L the head pointer of the linked list
  74. */
  75. void printList(Node* L) {
  76. Node* node = L->next;
  77. while (node) {
  78. std::cout << "node = " << node->data << std::endl;
  79. node = node->next;
  80. }
  81. }
  82. /**
  83. * Main function
  84. * @return 0
  85. */
  86. int main() {
  87. Node* L = initList();
  88. headInsert(L, 1);
  89. headInsert(L, 2);
  90. headInsert(L, 3);
  91. headInsert(L, 4);
  92. headInsert(L, 5);
  93. tailInsert(L, 6);
  94. tailInsert(L, 7);
  95. printList(L);
  96. if (deleteNode(L, 3)) {
  97. std::cout << "Success delete" << std::endl;
  98. }
  99. else {
  100. std::cout << "Fail delete" << std::endl;
  101. }
  102. printList(L);
  103. // Cleanup: free allocated memory
  104. Node* current = L;
  105. while (current) {
  106. Node* next = current->next;
  107. delete current;
  108. current = next;
  109. }
  110. return 0;
  111. }

 运行结果:

单循链表

单循环链表是一种链式存储的数据结构,它是线性表的一种链式存储结构的变体。在单循环链表中,除了保留单链表的基本特性外,其特殊之处在于最后一个结点的指针域不再是指向空(NULL),而是指回链表的头结点,这样就形成了一个环状结构。

单循环链表主要由以下部分组成:

  1. 结点(Node):每个结点包含两个部分,即数据域(Data Field)和指针域(Link Field)。

    • 数据域:用于存储具体的数据元素,它可以是任何类型的数据。
    • 指针域:也称链域,用于存储下一个结点的地址,指向链表中的下一个结点。
  2. 头结点(Header Node):单循环链表通常有一个头结点,它不存放实际数据或者也可以存放特定信息,并且它的指针域指向链表中的第一个实际数据结点。

  3. 链表结构:通过各个结点之间的指针连接形成一个闭环,从任一结点出发,沿着指针方向不断遍历,最终都能回到起点,即头结点。

因此,单循环链表的特点是可以在不修改指针的情况下,从任何一个结点开始都可以连续地遍历到链表的所有元素,提高了某些算法的效率,例如在查找、排序等操作中有一定优势。

  1. #include <iostream>
  2. #define TRUE 1
  3. #define FALSE 0
  4. /**
  5. * Define the struct of list node
  6. */
  7. struct Node {
  8. int data;
  9. Node* next;
  10. };
  11. /**
  12. * Initialize a linked list
  13. * @return the head pointer of the linked list's head
  14. */
  15. Node* initList() {
  16. Node* L = new Node();
  17. L->data = 0;
  18. L->next = L;
  19. return L;
  20. }
  21. /**
  22. * Insert an item at the beginning of the linked list
  23. * @param L the head pointer of the linked list
  24. * @param data the data you want to insert
  25. */
  26. void headInsert(Node* L, int data) {
  27. Node* node = new Node();
  28. node->data = data;
  29. node->next = L->next;
  30. L->next = node;
  31. L->data++;
  32. }
  33. /**
  34. * Insert an item at the end of the linked list
  35. * @param L the head pointer of the linked list
  36. * @param data the data you want to insert
  37. */
  38. void tailInsert(Node* L, int data) {
  39. Node* n = L;
  40. Node* node = new Node();
  41. node->data = data;
  42. while (n->next != L) {
  43. n = n->next; // 找到链表尾部
  44. }
  45. node->next = L; // 新节点的next指向头节点
  46. n->next = node; // 原尾节点的next指向新节点
  47. L->data++;
  48. }
  49. /**
  50. * Delete an item from the linked list
  51. * @param L the head pointer of the linked list
  52. * @param data the data you want to delete
  53. * @return success flag
  54. */
  55. int deleteNode(Node* L, int data) {
  56. // 将新节点的next指向原链表的第一个元素,
  57. // 再更新链表头的next指向新节点
  58. Node* preNode = L;
  59. Node* node = L->next;
  60. while (node != L) {
  61. if (node->data == data) {
  62. preNode->next = node->next;
  63. delete node;
  64. L->data--;
  65. return TRUE;
  66. }
  67. preNode = node;
  68. node = node->next;
  69. }
  70. return FALSE;
  71. }
  72. /**
  73. * Print all items in a linked list
  74. * @param L the head pointer of the linked list
  75. */
  76. void printList(Node* L) {
  77. Node* node = L->next;
  78. while (node != L) {
  79. std::cout << node->data << "->";
  80. node = node->next;
  81. }
  82. std::cout << "NULL" << std::endl;
  83. }
  84. /**
  85. * Main function
  86. * @return 0
  87. */
  88. int main() {
  89. Node* L = initList();
  90. headInsert(L, 1);
  91. headInsert(L, 2);
  92. headInsert(L, 3);
  93. headInsert(L, 4);
  94. headInsert(L, 5);
  95. tailInsert(L, 6);
  96. tailInsert(L, 7);
  97. printList(L);
  98. deleteNode(L, 4);
  99. deleteNode(L, 7);
  100. printList(L);
  101. return 0;
  102. }

 运行结果:

双链表

双链表(也称为双向链表)是链表的一种复杂形式,它是一种线性数据结构,由一系列节点(或称为元素)构成,每个节点包含两部分:

  1. 数据域:用于存储特定类型的数据元素。
  2. 指针域:每个节点有两个指针域,分别称为“后继指针”和“前驱指针”。后继指针指向该节点的直接后继节点,而前驱指针则指向前一个节点。

因此,在双向链表中,从任何一个节点出发,不仅可以找到其下一个节点(如同单链表),还可以找到其前一个节点。这样的设计使得在双向链表上的操作(如插入、删除和遍历)更加灵活,特别是在需要频繁进行双向遍历时更为高效。

  1. #include <iostream>
  2. #define TRUE 1
  3. #define FALSE 0
  4. /**
  5. * Define the struct of list node
  6. */
  7. struct Node {
  8. int data;
  9. Node* pre;
  10. Node* next;
  11. };
  12. /**
  13. * Initialize a linked list
  14. * @return the head pointer of the linked list
  15. */
  16. Node* initList() {
  17. Node* L = new Node();
  18. L->data = 0;
  19. L->pre = nullptr;
  20. L->next = nullptr;
  21. return L;
  22. }
  23. /**
  24. * Insert an item at the head of the linked list
  25. * @param L the head pointer of the linked list
  26. * @param data the data you want to insert
  27. */
  28. void headInsert(Node* L, int data) {
  29. Node* node = new Node();
  30. node->data = data;
  31. node->next = L->next;
  32. node->pre = L;
  33. if (L->next) {
  34. L->next->pre = node; // 如果原链表非空,那么原头节点的下一个节点的前驱指针应该指向新插入的节点
  35. L->next = node; // 更新原头节点的 next 指针使其指向新插入的节点
  36. }
  37. else {
  38. L->next = node; // 当链表为空时,新插入的节点成为链表的第一个节点
  39. }
  40. L->data++;
  41. }
  42. /**
  43. * Insert an item at the tail of the linked list
  44. * @param L the head pointer of the linked list
  45. * @param data the data you want to insert
  46. */
  47. void tailInsert(Node* L, int data) {
  48. Node* node = L;
  49. Node* n = new Node();
  50. n->data = data;
  51. while (node->next) {
  52. node = node->next; // 找到链表尾部的节点
  53. }
  54. n->next = node->next;
  55. node->next = n;
  56. n->pre = node;
  57. L->data++;
  58. }
  59. /**
  60. * Delete an item in the linked list
  61. * @param L the head pointer of the linked list
  62. * @param data the data you want to delete
  63. * @return success flag
  64. */
  65. int deleteNode(Node* L, int data) {
  66. Node* node = L->next;
  67. while (node) {
  68. if (node->data == data) {
  69. node->pre->next = node->next;
  70. if (node->next) {
  71. node->next->pre = node->pre;
  72. }
  73. L->data--;
  74. delete node;
  75. return TRUE;
  76. }
  77. node = node->next;
  78. }
  79. return FALSE;
  80. }
  81. /**
  82. * Print all items in a linked list
  83. * @param L the head pointer of the linked list
  84. */
  85. void printList(Node* L) {
  86. Node* node = L->next;
  87. while (node) {
  88. std::cout << node->data << " -> ";
  89. node = node->next;
  90. }
  91. std::cout << "NULL" << std::endl;
  92. }
  93. /**
  94. * Main function
  95. * @return null
  96. */
  97. int main() {
  98. Node* L = initList();
  99. headInsert(L, 1);
  100. headInsert(L, 2);
  101. headInsert(L, 3);
  102. headInsert(L, 4);
  103. tailInsert(L, 5);
  104. tailInsert(L, 6);
  105. printList(L);
  106. deleteNode(L, 6);
  107. printList(L);
  108. return 0;
  109. }

运行结果:

 

 

双循环列表

双循环链表是一种特殊类型的链表数据结构,它是双向链表与循环链表特性的结合。

组成部分:

  1. 节点(Node):双循环链表中的每个节点通常包含三个主要部分:

    • 数据域(Data Field):存储实际的数据元素或对象。
    • 前驱指针(Previous Pointer/Prev):指向该节点的直接前驱节点。
    • 后继指针(Next Pointer/Next):指向该节点的直接后继节点。
  2. 链表结构:整个链表通过这些节点相互连接形成,每个节点的“后继指针”指向下一个节点,“前驱指针”指向前一个节点。

  1. #include <iostream>
  2. /**
  3. * Define the struct of list node
  4. */
  5. struct Node {
  6. int data;
  7. Node* pre;
  8. Node* next;
  9. };
  10. /**
  11. * Init a linked list
  12. * @return The head pointer of the linked list's head
  13. */
  14. Node* initList() {
  15. Node* L = new Node();
  16. L->data = 0;
  17. L->pre = L;
  18. L->next = L;
  19. return L;
  20. }
  21. /**
  22. * Insert item at the head of the linked list
  23. * @param L The head pointer of the linked list
  24. * @param data The data you want to insert
  25. */
  26. void headInsert(Node* L, int data) {
  27. Node* node = new Node();
  28. node->data = data;
  29. node->next = L->next;
  30. node->pre = L;
  31. L->next->pre = node;
  32. L->next = node;
  33. L->data++;
  34. }
  35. /**
  36. * Insert item at the tail of the linked list
  37. * @param L The head pointer of the linked list
  38. * @param data The data you want to insert
  39. */
  40. void tailInsert(Node* L, int data) {
  41. Node* node = L;
  42. while (node->next != L) {
  43. node = node->next;
  44. }
  45. Node* n = new Node();
  46. n->data = data;
  47. n->pre = node;
  48. n->next = L;
  49. L->pre = n;
  50. node->next = n;
  51. L->data++;
  52. }
  53. /**
  54. * Delete item in the linked list
  55. * @param L The head pointer of the linked list
  56. * @param data The data you want to delete
  57. * @return Success flag
  58. */
  59. int deleteNode(Node* L, int data) {
  60. Node* node = L->next;
  61. while (node != L) {
  62. if (node->data == data) {
  63. node->pre->next = node->next;
  64. node->next->pre = node->pre;
  65. delete node;
  66. L->data--;
  67. return 1;
  68. }
  69. node = node->next;
  70. }
  71. return 0;
  72. }
  73. /**
  74. * Print all items in a linked list
  75. * @param L The head pointer of the linked list
  76. */
  77. void printList(Node* L) {
  78. Node* node = L->next;
  79. while (node != L) {
  80. std::cout << node->data << " -> ";
  81. node = node->next;
  82. }
  83. std::cout << "NULL" << std::endl;
  84. }
  85. /**
  86. * Main function
  87. * @return Null
  88. */
  89. int main() {
  90. Node* L = initList();
  91. headInsert(L, 1);
  92. headInsert(L, 2);
  93. headInsert(L, 4);
  94. headInsert(L, 5);
  95. printList(L);
  96. tailInsert(L, 6);
  97. tailInsert(L, 7);
  98. printList(L);
  99. deleteNode(L, 7);
  100. printList(L);
  101. return 0;
  102. }

运行结果:

 

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号