当前位置:   article > 正文

数据结构-二叉链表的结构与实现

二叉链表

目录

一、引言

二、什么是二叉链表

三、二叉链表的结构

四、二叉链表的实现

1. 创建二叉链表

2. 遍历二叉链表

3. 插入节点

4. 删除节点

五、应用场景

六、总结

七、代码示例


一、引言

数据结构是计算机科学中的重要概念,它是计算机程序设计的基础。二叉链表是一种常见的数据结构,它可以用来表示树形结构,如二叉树等。本篇博客将介绍二叉链表的结构与实现,以及它在实际应用中的应用场景。

二、什么是二叉链表

二叉链表是一种特殊的链表,它的每个节点都有两个指针,一个指向左子树,一个指向右子树。这种结构可以用来表示树形结构,如二叉树等。

三、二叉链表的结构

二叉链表的结构如下所示:

  1. struct TreeNode {
  2.     int val;
  3.     TreeNode *left;
  4.     TreeNode *right;
  5.     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
  6. };

其中,`val`表示节点的值,`left`和`right`分别表示左子树和右子树。

四、二叉链表的实现

1. 创建二叉链表

创建二叉链表的过程可以通过递归实现。具体实现如下:

  1. TreeNode* createTree() {
  2.     int val;
  3.     cin >> val;
  4.     if (val == -1) {
  5.         return NULL;
  6.     }
  7.     TreeNode* root = new TreeNode(val);
  8.     root->left = createTree();
  9.     root->right = createTree();
  10.     return root;
  11. }

在这个函数中,我们首先读取一个整数,如果这个整数为-1,则表示当前节点为空,返回`NULL`。否则,我们创建一个新的节点,并将这个整数作为节点的值。然后,递归创建左子树和右子树,并将它们分别赋值给当前节点的`left`和`right`指针。

2. 遍历二叉链表

遍历二叉链表有三种方式:前序遍历、中序遍历和后序遍历。它们的区别在于遍历的顺序不同。

前序遍历的实现如下:

  1. void preOrder(TreeNode* root) {
  2.     if (root == NULL) {
  3.         return;
  4.     }
  5.     cout << root->val << " ";
  6.     preOrder(root->left);
  7.     preOrder(root->right);
  8. }

在这个函数中,我们首先输出当前节点的值,然后递归遍历左子树和右子树。

中序遍历的实现如下:

  1. void inOrder(TreeNode* root) {
  2.     if (root == NULL) {
  3.         return;
  4.     }
  5.     inOrder(root->left);
  6.     cout << root->val << " ";
  7.     inOrder(root->right);
  8. }

在这个函数中,我们首先递归遍历左子树,然后输出当前节点的值,最后递归遍历右子树。

后序遍历的实现如下:

  1. void postOrder(TreeNode* root) {
  2.     if (root == NULL) {
  3.         return;
  4.     }
  5.     postOrder(root->left);
  6.     postOrder(root->right);
  7.     cout << root->val << " ";
  8. }

在这个函数中,我们首先递归遍历左子树和右子树,然后输出当前节点的值。

3. 插入节点

插入节点的过程可以通过递归实现。具体实现如下:

  1. TreeNode* insertNode(TreeNode* root, int val) {
  2.     if (root == NULL) {
  3.         return new TreeNode(val);
  4.     }
  5.     if (val < root->val) {
  6.         root->left = insertNode(root->left, val);
  7.     } else {
  8.         root->right = insertNode(root->right, val);
  9.     }
  10.     return root;
  11. }

在这个函数中,我们首先判断当前节点是否为空,如果为空,则创建一个新的节点,并将它作为当前节点的子节点。否则,我们比较要插入的值和当前节点的值的大小关系,如果要插入的值小于当前节点的值,则递归插入到左子树中,否则递归插入到右子树中。

4. 删除节点

删除节点的过程可以通过递归实现。具体实现如下:

  1. TreeNode* deleteNode(TreeNode* root, int val) {
  2.     if (root == NULL) {
  3.         return NULL;
  4.     }
  5.     if (val < root->val) {
  6.         root->left = deleteNode(root->left, val);
  7.     } else if (val > root->val) {
  8.         root->right = deleteNode(root->right, val);
  9.     } else {
  10.         if (root->left == NULL) {
  11.             TreeNode* tmp = root->right;
  12.             delete root;
  13.             return tmp;
  14.         } else if (root->right == NULL) {
  15.             TreeNode* tmp = root->left;
  16.             delete root;
  17.             return tmp;
  18.         } else {
  19.             TreeNode* tmp = root->right;
  20.             while (tmp->left != NULL) {
  21.                 tmp = tmp->left;
  22.             }
  23.             root->val = tmp->val;
  24.             root->right = deleteNode(root->right, tmp->val);
  25.         }
  26.     }
  27.     return root;
  28. }

在这个函数中,我们首先判断当前节点是否为空,如果为空,则返回`NULL`。否则,我们比较要删除的值和当前节点的值的大小关系

这段代码是一个二叉搜索树的删除节点操作。二叉搜索树是一种特殊的二叉树,它的每个节点都比它的左子树中的所有节点大,比它的右子树中的所有节点小。删除节点的操作需要考虑三种情况:

1. 要删除的节点没有子节点,直接删除即可。

2. 要删除的节点只有一个子节点,将子节点替换要删除的节点即可。

3. 要删除的节点有两个子节点,需要找到右子树中最小的节点,将它的值赋给要删除的节点,然后再删除右子树中最小的节点。

这段代码使用递归实现了二叉搜索树的删除节点操作。如果要删除的节点比当前节点小,就递归到左子树中删除;如果要删除的节点比当前节点大,就递归到右子树中删除;如果要删除的节点就是当前节点,就按照上述三种情况进行处理。最后返回根节点。

好的,下面是五、应用场景和六、总结的内容:

五、应用场景

1. 二叉链表可以用于实现二叉树,二叉树是一种常用的数据结构,广泛应用于计算机科学和工程领域。

2. 二叉链表可以用于实现哈夫曼树,哈夫曼树是一种带权路径长度最短的树,广泛应用于数据压缩和编码领域。

3. 二叉链表可以用于实现二叉堆,二叉堆是一种基于完全二叉树的数据结构,广泛应用于堆排序、优先队列等算法中。

4. 二叉链表可以用于实现二叉搜索树,二叉搜索树是一种特殊的二叉树,广泛应用于查找、排序、删除等算法中。

六、总结

二叉链表是一种常用的数据结构,它可以用于实现二叉树、哈夫曼树、二叉堆、二叉搜索树等算法。二叉链表的结构相对简单,实现起来也比较容易,但是需要注意指针的使用,避免出现空指针和死循环等问题。在实际应用中,我们需要根据具体的需求选择合适的数据结构,以提高算法的效率和性能。

七、代码示例

以下是C++的二叉链表的完整实现代码,包括节点的定义、插入、删除、查找、遍历等操作:

  1. #include <iostream>
  2. using namespace std;
  3. // 二叉树节点定义
  4. struct TreeNode {
  5.     int val;
  6.     TreeNode* left;
  7.     TreeNode* right;
  8.     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
  9. };
  10. // 二叉树类定义
  11. class BinaryTree {
  12. public:
  13.     BinaryTree() : root(nullptr) {}
  14.     ~BinaryTree() { destroy(root); }
  15.     // 插入节点
  16.     void insert(int val) {
  17.         insert(root, val);
  18.     }
  19.     // 删除节点
  20.     void remove(int val) {
  21.         remove(root, val);
  22.     }
  23.     // 查找节点
  24.     bool find(int val) {
  25.         return find(root, val);
  26.     }
  27.     // 前序遍历
  28.     void preOrder() {
  29.         preOrder(root);
  30.     }
  31.     // 中序遍历
  32.     void inOrder() {
  33.         inOrder(root);
  34.     }
  35.     // 后序遍历
  36.     void postOrder() {
  37.         postOrder(root);
  38.     }
  39. private:
  40.     TreeNode* root;
  41.     // 插入节点
  42.     void insert(TreeNode*& node, int val) {
  43.         if (node == nullptr) {
  44.             node = new TreeNode(val);
  45.         } else if (val < node->val) {
  46.             insert(node->left, val);
  47.         } else if (val > node->val) {
  48.             insert(node->right, val);
  49.         }
  50.     }
  51.     // 删除节点
  52.     void remove(TreeNode*& node, int val) {
  53.         if (node == nullptr) {
  54.             return;
  55.         } else if (val < node->val) {
  56.             remove(node->left, val);
  57.         } else if (val > node->val) {
  58.             remove(node->right, val);
  59.         } else {
  60.             if (node->left == nullptr && node->right == nullptr) {
  61.                 delete node;
  62.                 node = nullptr;
  63.             } else if (node->left == nullptr) {
  64.                 TreeNode* temp = node;
  65.                 node = node->right;
  66.                 delete temp;
  67.             } else if (node->right == nullptr) {
  68.                 TreeNode* temp = node;
  69.                 node = node->left;
  70.                 delete temp;
  71.             } else {
  72.                 TreeNode* temp = findMin(node->right);
  73.                 node->val = temp->val;
  74.                 remove(node->right, temp->val);
  75.             }
  76.         }
  77.     }
  78.     // 查找节点
  79.     bool find(TreeNode* node, int val) {
  80.         if (node == nullptr) {
  81.             return false;
  82.         } else if (val < node->val) {
  83.             return find(node->left, val);
  84.         } else if (val > node->val) {
  85.             return find(node->right, val);
  86.         } else {
  87.             return true;
  88.         }
  89.     }
  90.     // 查找最小节点
  91.     TreeNode* findMin(TreeNode* node) {
  92.         while (node->left != nullptr) {
  93.             node = node->left;
  94.         }
  95.         return node;
  96.     }
  97.     // 前序遍历
  98.     void preOrder(TreeNode* node) {
  99.         if (node != nullptr) {
  100.             cout << node->val << " ";
  101.             preOrder(node->left);
  102.             preOrder(node->right);
  103.         }
  104.     }
  105.     // 中序遍历
  106.     void inOrder(TreeNode* node) {
  107.         if (node != nullptr) {
  108.             inOrder(node->left);
  109.             cout << node->val << " ";
  110.             inOrder(node->right);
  111.         }
  112.     }
  113.     // 后序遍历
  114.     void postOrder(TreeNode* node) {
  115.         if (node != nullptr) {
  116.             postOrder(node->left);
  117.             postOrder(node->right);
  118.             cout << node->val << " ";
  119.         }
  120.     }
  121.     // 销毁节点
  122.     void destroy(TreeNode* node) {
  123.         if (node != nullptr) {
  124.             destroy(node->left);
  125.             destroy(node->right);
  126.             delete node;
  127.         }
  128.     }
  129. };
  130. // 测试代码
  131. int main() {
  132.     BinaryTree tree;
  133.     tree.insert(5);
  134.     tree.insert(3);
  135.     tree.insert(7);
  136.     tree.insert(1);
  137.     tree.insert(4);
  138.     tree.insert(6);
  139.     tree.insert(8);
  140.     cout << "前序遍历: ";
  141.     tree.preOrder();
  142.     cout << endl;
  143.     cout << "中序遍历: ";
  144.     tree.inOrder();
  145.     cout << endl;
  146.     cout << "后序遍历: ";
  147.     tree.postOrder();
  148.     cout << endl;
  149.     cout << "查找节点 4: " << (tree.find(4) ? "存在" : "不存在") << endl;
  150.     tree.remove(3);
  151.     cout << "删除节点 3 后的中序遍历: ";
  152.     tree.inOrder();
  153.     cout << endl;
  154.     return 0;
  155. }

输出示例:
前序遍历: 5 3 1 4 7 6 8 
中序遍历: 1 3 4 5 6 7 8 
后序遍历: 1 4 3 6 8 7 5 
查找节点 4: 存在
删除节点 3 后的中序遍历: 1 4 5 6 7 8 
 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/703414
推荐阅读
相关标签
  

闽ICP备14008679号