当前位置:   article > 正文

二叉树的定义与C++实现_c++定义二叉树结构体

c++定义二叉树结构体

        树,是有限节点的集合。生活中的树是树根在下面,数据结构中的树的根在顶部,如下图:

        公司的人员组织架构,董事长,总经理,副总。。。,这种模型可以用二叉树表示,还有一些压缩算法也用到了树结构。

树的几个概念

(1)度:有几个直接的孩子,例如,A的度是3,它有BCD三个孩子,B的度是2,它有EF两个孩子,度为0的节点也就是叶子节点(终端节点)

(2)祖先:E的祖先是B,A , 从当前节点一直往上找

(3)叶子节点:下面的一层称为叶子节点,也可以称为终端节点。

(4)根:非叶子节点。

(5)树的深度,如下图

 (6)森林:不交叉的几棵树在一起称为森林

二叉树

       所有节点的度都小于等于2的树称为二叉树。下面这几种都可以称为二叉树

1、二叉树的遍历

       3种遍历方式,根据根节点的位置,分为前序,中序,后序。

                                                                               前序:左右,ABC

                                                                              中序 :左根右, BAC

                                                                        后序遍历:左右根, BCA

       例如下面这颗二叉树

          从根节点A在结果中的位置也可以看出是那种遍历方式。

2、二叉树的存储结构

     (1)顺序存储,类似于数组,例如下面这颗二叉树,在数组中的存储是:3561972

       数组存储时,如果节点不存在就用0表示,例如下面的,在数组中就是35019

        顺序存储可以作为一种特殊形式,有相关需求时可以采用,

     (2)链式存储,这是二叉树最好的存储形式,用一个结构体表示节点,有数据成员,指向左子树的指针,指向右子树的指针。

        

3、满二叉树与完全二叉树

       完全二叉树的定义:如果二叉树的深度为h, 除h层外,其它各层的节点数都达到最大数,且第h层的所有节点都连续集中在最左边,这种二叉树称为完全二叉树。

       

      

C++实现二叉树

     下面介绍如何用数组和链表,例如实现下面这颗树

  基于数组的二叉树实现 

  头文件TreeArray.h

  1. /*
  2. 用数组实现二叉树
  3. */
  4. #pragma once
  5. //节点的插入方向
  6. enum DIRECTION
  7. {
  8. LEFT,
  9. RIGHT
  10. };
  11. class TreeArray
  12. {
  13. public:
  14. TreeArray(int size, int *pRoot); //构造创建树
  15. ~TreeArray(); //销毁树
  16. int *SearchNode(int nodeIndex);
  17. bool AddNode(int nodeIndex, DIRECTION dirc, int *pNode);
  18. bool DeleteNode(int nodeIndex, int *pNode);
  19. void TreeTraverse(); //遍历树
  20. private:
  21. int *m_pTree;
  22. int m_iSize; //树的容量
  23. };

   TreeArray.cpp

  1. #include "TreeArray.h"
  2. #include <iostream>
  3. using namespace std;
  4. TreeArray::TreeArray(int size,int *pRoot)
  5. {
  6. if (size > 0)
  7. {
  8. m_iSize = size;
  9. m_pTree = new int[size];
  10. for (int i = 0; i < size; i++)
  11. {
  12. m_pTree[i] = 0;
  13. }
  14. m_pTree[0] = *pRoot;
  15. }
  16. else
  17. {
  18. m_iSize = 0;
  19. m_pTree = nullptr;
  20. }
  21. }
  22. TreeArray::~TreeArray()
  23. {
  24. if (m_pTree != nullptr)
  25. {
  26. delete[] m_pTree;
  27. m_pTree = nullptr;
  28. }
  29. }
  30. int * TreeArray::SearchNode(int nodeIndex)
  31. {
  32. if (nodeIndex < m_iSize && m_pTree >= 0)
  33. {
  34. if (m_pTree[nodeIndex] == 0) //0表示空节点
  35. {
  36. return nullptr;
  37. }
  38. }
  39. else
  40. {
  41. return nullptr;
  42. }
  43. return &m_pTree[nodeIndex];
  44. }
  45. bool TreeArray::AddNode(int nodeIndex, DIRECTION dirc, int * pNode)
  46. {
  47. if (nodeIndex < 0 || nodeIndex >= m_iSize)
  48. {
  49. return false;
  50. }
  51. if (m_pTree[nodeIndex] == 0)
  52. {
  53. return false;
  54. }
  55. if (dirc == LEFT)
  56. {
  57. int insertId = nodeIndex * 2 + 1;
  58. if (insertId >= m_iSize)
  59. {
  60. return false;
  61. }
  62. if (m_pTree[insertId] != 0)
  63. {
  64. return false;
  65. }
  66. m_pTree[insertId] = *pNode;
  67. }
  68. else if (dirc == RIGHT)
  69. {
  70. int insertId = nodeIndex * 2 + 2;
  71. if (insertId >= m_iSize)
  72. {
  73. return false;
  74. }
  75. if (m_pTree[insertId] != 0)
  76. {
  77. return false;
  78. }
  79. m_pTree[insertId] = *pNode;
  80. }
  81. return true;
  82. }
  83. bool TreeArray::DeleteNode(int nodeIndex, int * pNode)
  84. {
  85. if (nodeIndex < 0 || nodeIndex >= m_iSize)
  86. {
  87. return false;
  88. }
  89. if (m_pTree[nodeIndex] == 0)
  90. {
  91. return false;
  92. }
  93. *pNode = m_pTree[nodeIndex];
  94. m_pTree[nodeIndex] = 0;
  95. return true;
  96. }
  97. void TreeArray::TreeTraverse()
  98. {
  99. for (int i = 0; i<m_iSize; i++)
  100. {
  101. cout << m_pTree[i] << " ";
  102. }
  103. cout << endl;
  104. }

  main函数测试

  1. #include <iostream>
  2. #include "TreeArray.h"
  3. using namespace std;
  4. int main()
  5. {
  6. int root = 666;
  7. TreeArray *pTree = new TreeArray(10, &root);
  8. int node1 = 500;
  9. int node2 = 800;
  10. pTree->AddNode(0, LEFT, &node1);
  11. pTree->AddNode(0, RIGHT, &node2);
  12. int node3 = 200;
  13. int node4 = 600;
  14. pTree->AddNode(1, LEFT, &node3);
  15. pTree->AddNode(1, RIGHT, &node4);
  16. int node5 = 900;
  17. int node6 = 700;
  18. pTree->AddNode(2, LEFT, &node5);
  19. pTree->AddNode(2, RIGHT, &node6);
  20. //遍历
  21. pTree->TreeTraverse();
  22. //查找
  23. int *pValue = pTree->SearchNode(3);
  24. cout << "index = 3的节点值是" << *pValue << endl;
  25. //删除
  26. int dValue = 0;
  27. pTree->DeleteNode(6, &dValue);
  28. //遍历
  29. pTree->TreeTraverse();
  30. delete pTree;
  31. return 0;
  32. }

 运行结果

 基于链表的二叉树实现

        用链表实现二叉树,得先定义好二叉树的节点类型,根据二叉树的性质,节点得有5个属性:索引、数据 、左孩子指针、右孩子指针 、父结点指针 。如下所示:

  1. struct Node
  2. {
  3. int index;
  4. int data;
  5. Node *pLChild; //左子树
  6. Node *pRChild; //右字数
  7. Node *pParent; //父节点
  8. };

 还得实现3种遍历方式,使用递归遍历是比较方便的。具体代码如下

      Tree.h

  1. #ifndef TREE_H
  2. #define TREE_H
  3. #include <iostream>
  4. using namespace std;
  5. //树的节点
  6. struct Node
  7. {
  8. Node(int _data = 0);
  9. Node *SearchNode(int nodeIndex);
  10. void DeleteNode();
  11. void PreOrderTraversal();
  12. void MiddleOrderTraversal();
  13. void LastOrderTraversal();
  14. int index;
  15. int data;
  16. Node *pLChild; //左子树
  17. Node *pRChild; //右字数
  18. Node *pParent; //父节点
  19. };
  20. //节点的插入方向
  21. enum DIRECTION
  22. {
  23. LEFT,
  24. RIGHT
  25. };
  26. //二叉树
  27. class Tree
  28. {
  29. public:
  30. Tree(int data = 0); //创建树
  31. ~Tree(); //销毁树
  32. Node *SearchNode(int nodeIndex); //搜索结点
  33. bool AddNode(int nodeIndex, DIRECTION direction, Node *pNode); //添加结点
  34. bool DeleteNode(int nodeIndex, Node *pNode); //删除结点
  35. void PreOrderTraversal(); //前序遍历
  36. void MiddleOrderTraversal(); //中序遍历
  37. void LastOrderTraversal(); //后序遍历
  38. private:
  39. Node *m_pRoot;
  40. };
  41. #endif

  Tree.cpp

  1. #include "Tree.h"
  2. Node::Node(int _data)
  3. {
  4. index = 0;
  5. data = _data;
  6. pLChild = NULL;
  7. pRChild = NULL;
  8. pParent = NULL;
  9. }
  10. Node *Node::SearchNode(int nodeIndex)
  11. {
  12. if (this->index == nodeIndex)
  13. {
  14. return this;
  15. }
  16. Node *temp = NULL;
  17. if (this->pLChild != NULL)
  18. {
  19. if (this->pLChild->index == nodeIndex)
  20. {
  21. return this->pLChild;
  22. }
  23. else
  24. {
  25. temp = this->pLChild->SearchNode(nodeIndex);
  26. if (temp != NULL)
  27. {
  28. return temp;
  29. }
  30. }
  31. }
  32. if (this->pRChild != NULL)
  33. {
  34. if (this->pRChild->index == nodeIndex)
  35. {
  36. return this->pRChild;
  37. }
  38. else
  39. {
  40. temp = this->pRChild->SearchNode(nodeIndex);
  41. if (temp != NULL)
  42. {
  43. return temp;
  44. }
  45. }
  46. }
  47. return NULL;
  48. }
  49. void Node::DeleteNode()
  50. {
  51. if (this->pLChild != NULL)
  52. {
  53. this->pLChild->DeleteNode();
  54. }
  55. if (this->pRChild != NULL)
  56. {
  57. this->pRChild->DeleteNode();
  58. }
  59. if (this->pParent != NULL)
  60. {
  61. if (this->pParent->pLChild == this)
  62. {
  63. this->pParent->pLChild = NULL;
  64. }
  65. if (this->pParent->pRChild == this)
  66. {
  67. this->pParent->pRChild = NULL;
  68. }
  69. }
  70. delete this;
  71. }
  72. void Node::PreOrderTraversal()
  73. {
  74. cout << this->index << " " << this->data << endl;
  75. if (this->pLChild != NULL)
  76. {
  77. this->pLChild->PreOrderTraversal();
  78. }
  79. if (this->pRChild != NULL)
  80. {
  81. this->pRChild->PreOrderTraversal();
  82. }
  83. }
  84. void Node::MiddleOrderTraversal()
  85. {
  86. if (this->pLChild != NULL)
  87. {
  88. this->pLChild->MiddleOrderTraversal();
  89. }
  90. cout << this->index << " " << this->data << endl;
  91. if (this->pRChild != NULL)
  92. {
  93. this->pRChild->MiddleOrderTraversal();
  94. }
  95. }
  96. void Node::LastOrderTraversal()
  97. {
  98. if (this->pLChild != NULL)
  99. {
  100. this->pLChild->LastOrderTraversal();
  101. }
  102. if (this->pRChild != NULL)
  103. {
  104. this->pRChild->LastOrderTraversal();
  105. }
  106. cout << this->index << " " << this->data << endl;
  107. }
  108. Tree::Tree(int data)
  109. {
  110. m_pRoot = new Node(data);
  111. }
  112. Tree::~Tree()
  113. {
  114. //DeleteNode(0, NULL);
  115. m_pRoot->DeleteNode();
  116. }
  117. Node *Tree::SearchNode(int nodeIndex)
  118. {
  119. return m_pRoot->SearchNode(nodeIndex);
  120. }
  121. bool Tree::AddNode(int nodeIndex, DIRECTION direction, Node *pNode)
  122. {
  123. Node *temp = SearchNode(nodeIndex);
  124. if(temp == NULL)
  125. {
  126. return false;
  127. }
  128. Node *node = new Node();
  129. if(node == NULL)
  130. {
  131. return false;
  132. }
  133. node->index = pNode->index;
  134. node->data = pNode->data;
  135. node->pParent = temp;
  136. if(direction == LEFT)
  137. {
  138. temp->pLChild = node;
  139. }
  140. if(direction == RIGHT)
  141. {
  142. temp->pRChild = node;
  143. }
  144. return true;
  145. }
  146. bool Tree::DeleteNode(int nodeIndex, Node *pNode)
  147. {
  148. Node *temp = SearchNode(nodeIndex);
  149. if(temp == NULL)
  150. {
  151. return false;
  152. }
  153. if(pNode != NULL)
  154. {
  155. pNode->data = temp->data;
  156. }
  157. temp->DeleteNode();
  158. return true;
  159. }
  160. void Tree::PreOrderTraversal()
  161. {
  162. m_pRoot->PreOrderTraversal();
  163. }
  164. void Tree::MiddleOrderTraversal()
  165. {
  166. m_pRoot->MiddleOrderTraversal();
  167. }
  168. void Tree::LastOrderTraversal()
  169. {
  170. m_pRoot->LastOrderTraversal();
  171. }

 main方法测试:

  1. #include <iostream>
  2. #include "Tree.h"
  3. int main(void)
  4. {
  5. Node *node1 = new Node();
  6. node1->index = 1;
  7. node1->data = 500;
  8. Node *node2 = new Node();
  9. node2->index = 2;
  10. node2->data = 800;
  11. Node *node3 = new Node();
  12. node3->index = 3;
  13. node3->data = 200;
  14. Node *node4 = new Node();
  15. node4->index = 4;
  16. node4->data = 600;
  17. Node *node5 = new Node();
  18. node5->index = 5;
  19. node5->data = 900;
  20. Node *node6 = new Node();
  21. node6->index = 6;
  22. node6->data = 700;
  23. Tree *tree = new Tree(666);
  24. tree->AddNode(0, LEFT, node1);
  25. tree->AddNode(0, RIGHT, node2);
  26. tree->AddNode(1, LEFT, node3);
  27. tree->AddNode(1, RIGHT, node4);
  28. tree->AddNode(2, LEFT, node5);
  29. tree->AddNode(2, RIGHT, node6);
  30. //tree->DeleteNode(6, NULL);
  31. //tree->DeleteNode(5, NULL);
  32. tree->DeleteNode(2, NULL);
  33. tree->PreOrderTraversal();
  34. //tree->MiddleOrderTraversal();
  35. //tree->LastOrderTraversal();
  36. delete tree;
  37. system("pause");
  38. return 0;
  39. }

 以上就是二叉树的两种实现方,推荐使用链表的形式。

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

闽ICP备14008679号