鱼C论坛

 找回密码
 立即注册
查看: 2287|回复: 0

[学习笔记] 链式存储二叉树

[复制链接]
发表于 2018-5-4 10:40:27 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
《数据结构C++语言描述》 清华大学出版社, 任燕编著

小弟去除了书中一些没有必要的方法,同时还自己写了一个用链式存储自递归方式创建二叉树的方法
嵌入在默认构造函数里,小弟也是很恼火为什么书上这个喜欢顺序存储的二叉树,什么都要从那个二叉树里转化过来,,,,
  1. /*
  2. *二叉树遍历是非常重要的操作,
  3. *二叉树的三种常见的前序,中序,后序递归遍历真的很有意思
  4. *二叉树的操作你会发现离不开递归,递归再解决二叉树链式存储方面真的好用
  5. *遇到不会的问题就要在纸上画一画,会遇到很多常规操作,要牢记
  6. *一些类模板的用法平时要进行知识点的累计和记忆,这种语法问题在C++中非常重要
  7. *have fun
  8. */

  9. #include <iostream>
  10. #include <cstdlib>
  11. #include <cstdbool>
  12. #include <assert.h>
  13. using namespace std;

  14. //嵌入头文件
  15. #ifndef MYSEQTREE_H
  16. #define MYSEQTREE_H
  17. #include "C://Users//pc//Desktop//BinaryTree//ConsoleApplication1//MySeqTree.cpp"
  18. #endif


  19. #define LH 1                //左高
  20. #define EH 0                //等高
  21. #define RH -1                //右高

  22. template <typename elemtype>
  23. class BiTree{
  24. public:
  25.         //二叉树,链表存储结点的数据结构
  26.         class Node{
  27.         public:
  28.                 Node() :lchild(NULL), rchild(NULL){};                //初始化构造函数

  29.                 elemtype data;                //结点的数据域
  30.                 class Node* lchild, *rchild;        //左右孩子指针
  31.         };

  32.         typedef Node* NodePointer;                //指向结点的指针类型声明

  33. public:

  34.         //链式存储构造二叉树
  35.         void createBiTree(NodePointer &p);                //这里要取引用

  36.         //二叉树置空
  37.         void clear();

  38.         //求二叉树的叶子数
  39.         int countLeaf();

  40.         //求二叉树的节点数
  41.         int countNode();

  42.         //递归求二叉树的深度
  43.         int depth();

  44.         //显示二叉树的顺序存储
  45.         void displaySeqTree();

  46.         //交换二叉树中所有结点的左右子树
  47.         void exchangeLRchild();

  48.         //取根指针
  49.         NodePointer getRoot();

  50.         //中序递归遍历二叉树
  51.         void inOrderTraverse();

  52.         //判断是否为空的二叉树
  53.         bool isEmpty();

  54.         //按层次顺序遍历二叉树
  55.         void layOrderTraverse();

  56.         //二叉树的二叉链表存储转化位顺序存储结构
  57.         void linkToSequential();

  58.         //非递归中序遍历二叉树
  59.         void noRecursionInOrderTraverse();

  60.         //后续递归遍历二叉树
  61.         void postOrderTraverse();

  62.         //前序递归遍历二叉树
  63.         void preOrderTraverse();

  64.         //随机生成一棵二叉树
  65.         void randomCreate();

  66.         //二叉树的顺序存储转化为二叉链表存储的数据结构
  67.         //void sequentialToLink(MySeqTree<elemtype> T);

  68. private:
  69.         //拷贝初始化构造函数的辅助函数
  70.         void BiTree_aux(NodePointer &p, NodePointer otherP);

  71.         //求二叉树叶子数的辅助函数
  72.         int countLeaf_aux(NodePointer p);

  73.         //求二叉树结点数的辅助函数
  74.         int countNode_aux(NodePointer p);

  75.         //回收二叉树结点存储空间的辅助函数
  76.         void deleteNode_aux(NodePointer p);

  77.         //递归求二叉树深度的辅助函数
  78.         int depth_aux(NodePointer p);

  79.         //交换二叉树中所有的结点的左右子树的辅助函数
  80.         void exchangeLRchild_aux(NodePointer p);

  81.         //中序递归遍历二叉树的辅助函数
  82.         void inOrderTraverse_aux(NodePointer p);

  83.         //二叉树的二叉链表转化为顺序存储结构的辅助函数
  84.         void linkToSequential_aux(MySeqTree<elemtype> &tempT, NodePointer p, int i);


  85.         //后序递归遍历二叉树的辅助函数
  86.         void postOrderTraverse_aux(NodePointer p);

  87.         //前序递归遍历二叉树的辅助函数
  88.         void preOrderTraverse_aux(NodePointer p);

  89.         //二叉树的顺序存储转化为二叉链表存储结构的辅助函数
  90.         void sequentialToLink_aux(int i, NodePointer& subroot);

  91. public:

  92.         //构造函数
  93.         BiTree();

  94.         //二叉树析构函数
  95.         virtual ~BiTree();

  96.         //拷贝初始化构造函数
  97.         BiTree(const BiTree<elemtype> &otherT);

  98.         //输入二叉树,采用二叉链表存储
  99.         void read(istream& in);

  100.         //输出二叉树,采用二叉链表存储
  101.         void display(ostream& out);

  102. protected:
  103.         NodePointer root;                        //二叉树的根指针
  104.         MySeqTree<elemtype> seqT;  //二叉树对应的顺序存储树

  105. };





  106. //把二叉树置空,通过指针递归实现,借助deleteNode_aux,从根指针root开始递归
  107. template <typename elemtype>
  108. void BiTree<elemtype>::clear(){
  109.         seqT.clear();                                //回收二叉树对应顺序存储的空间
  110.         deleteNode_aux(root);                //逐一回收二叉树的每一个结点的存储结点
  111.         root = NULL;                                //二叉树根指针置空
  112. }

  113. //回收二叉树结点存储空间的辅助函数
  114. //输入:函数的值参指针p指向待回收的结点
  115. //后序遍历

  116. template <typename elemtype>
  117. void BiTree<elemtype>::deleteNode_aux(NodePointer p){
  118.         //按照后序遍历方式逐一回收每一个结点
  119.         if (p){
  120.                 deleteNode_aux(p->lchild);                //自递归回收左子树结点
  121.                 deleteNode_aux(p->rchild);                //自递归回收右子树结点
  122.                 delete p;                                                //回收指针p所指的存储空间
  123.         }
  124. }


  125. //求二叉树的也指数
  126. //输出:二叉树的叶子数
  127. //借助coutLeaf_aux从根指针root进行递归
  128. template <typename elemtype>
  129. int BiTree<elemtype>::countLeaf(){
  130.         return countLeaf_aux(root);
  131. }

  132. //求二叉树叶子数的辅助函数
  133. //输入:函数的值参指针p指向带判断是否为叶子的结点
  134. //输出:如果指针p指向根节点,函数的返回值返回最终的叶子结点数

  135. template <typename elemtype>
  136. int BiTree<elemtype>::countLeaf_aux(NodePointer p){
  137.         int num = 0;                                //预存放最终的叶子节点数
  138.         static int i = 0;                //存放叶子结点的累计数,初始化为0
  139.         if (p){
  140.                 if (!p->lchild && !p->rchild){                //找到了叶子
  141.                         i++;
  142.                 }

  143.                 countLeaf_aux(p->lchild);                //自递归求左子树的叶子结点数
  144.                 countLeaf_aux(p->rchild);                //自递归求右子树的叶子结点数
  145.         }

  146.         if (p == root){
  147.                 num = i;
  148.                 i = 0;                //static 最后要清零,你懂的
  149.         }
  150.         return num;
  151. }

  152. //求二叉树的结点数
  153. template <typename elemtype>
  154. int BiTree<elemtype>::countNode(){
  155.         return countNode_aux(root);
  156. }

  157. //求二叉树结点数的辅助函数
  158. template <typename elemtype>
  159. int BiTree<elemtype>::countNode_aux(NodePointer p){
  160.         int num = 0;                //预存放最终的节点数
  161.         static int i = 0;                //类似前面计算叶子数的,你懂的

  162.         if (p){
  163.                 i++;                        //结点数加一
  164.                 countNode_aux(p->lchild);                //自递归遍历左子树
  165.                 countNode_aux(p->rchild);                //自递归遍历右子树
  166.         }

  167.         if (p == root){
  168.                 num = i;
  169.                 i = 0;
  170.         }
  171.         return num;
  172. }


  173. //递归求二叉树深度
  174. template <typename elemtype>
  175. int BiTree<elemtype>::depth(){
  176.         return depth_aux(root);
  177. }

  178. //递归求二叉树深度辅助函数
  179. template <typename elemtype>
  180. int BiTree<elemtype>::depth_aux(NodePointer p){
  181.         int lDep;                //预存放左子树的深度
  182.         int rDep;                //预存放右子树的深度
  183.         if (!p){
  184.                 return 0;                //空树返回零
  185.         }
  186.         else{
  187.                 lDep = depth_aux(p->lchild);
  188.                 rDep = depth_aux(p->rchild);

  189.                 return (lDep > rDep ? lDep : rDep) + 1;                //这个递归不同于之前的递归,有意思
  190.         }
  191. }

  192. //取根指针
  193. //输出:根指针
  194. template <typename elemtype>
  195. typename BiTree<elemtype>::NodePointer BiTree<elemtype>::getRoot(){                //注意这里的写法
  196.                 return root;
  197. }

  198. //中序递归遍历二叉树
  199. //从根指针root进行递归
  200. template <typename elemtype>
  201. void BiTree<elemtype>::inOrderTraverse(){
  202.         inOrderTraverse_aux(root);
  203. }

  204. //中序递归遍历二叉树辅助函数
  205. template <typename elemtype>
  206. void BiTree<elemtype>::inOrderTraverse_aux(NodePointer p){
  207.         if (p){
  208.                 cout << "hahhahahhahah" << endl;
  209.                 inOrderTraverse_aux(p->lchild);                //用指针p->lchild自递归遍历左子树的结点
  210.                 cout << p->data << "\t";                                        //遍历p所指向的结点
  211.                 inOrderTraverse_aux(p->rchild);                //用指针p->rchild自递归遍历右子树的结点
  212.         }
  213. }


  214. //判断是否为空的二叉树
  215. template <typename elemtype>
  216. bool BiTree<elemtype>::isEmpty(){
  217.         return root ? false : true;
  218. }

  219. //后序递归遍历二叉树
  220. template <typename elemtype>
  221. void BiTree<elemtype>::postOrderTraverse(){
  222.         postOrderTraverse_aux(root);
  223. }

  224. //后序递归遍历二叉树辅助函数
  225. template <typename elemtype>
  226. void BiTree<elemtype>::postOrderTraverse_aux(NodePointer p){
  227.         if (p){
  228.                 postOrderTraverse_aux(p->lchild);
  229.                 postOrderTraverse_aux(p->rchild);
  230.                 cout << p->data << "\t";
  231.         }
  232. }

  233. //前序递归遍历二叉树
  234. template <typename elemtype>
  235. void BiTree<elemtype>::preOrderTraverse(){
  236.         preOrderTraverse_aux(root);
  237. }

  238. //前序递归遍历二叉树辅助函数
  239. template <typename elemtype>
  240. void BiTree<elemtype>::preOrderTraverse_aux(NodePointer p){
  241.         if (p){
  242.                 cout << p->data << "\t";
  243.                 preOrderTraverse_aux(p->lchild);
  244.                 preOrderTraverse_aux(p->rchild);
  245.         }
  246. }


  247. //二叉树的构造函数
  248. template <typename elemtype>
  249. BiTree<elemtype>::BiTree(){
  250.         root = NULL;
  251.         createBiTree(root);
  252. }

  253. //链式存储创建二叉树
  254. template <typename elemtype>
  255. void BiTree<elemtype>::createBiTree(NodePointer &p){
  256.         cout << "请输入数字,要想停止左或右创建要输入多次零:";
  257.         elemtype value;
  258.         cin >> value;
  259.         if (value == 0){
  260.                 p = NULL;
  261.         }
  262.         else{
  263.                 p = new Node;
  264.                 assert(p != 0);
  265.                 p->data = value;
  266.                 createBiTree(p->lchild);                //自递归创建左子树
  267.                 createBiTree(p->rchild);                //自递归创建右子树
  268.         }
  269. }



  270. //析构函数
  271. template <typename elemtype>
  272. BiTree<elemtype>::~BiTree(){
  273.         clear();
  274. }



  275. int main(int argc, char *argv[]){
  276.         BiTree<int> bt1;

  277.         cout << "结点数:";
  278.         cout << bt1.countNode() << endl;
  279.         cout << "叶子数:";
  280.         cout << bt1.countLeaf() << endl;
  281.         cout << "中序遍历:" << endl;
  282.         bt1.inOrderTraverse();
  283.         return 0;
  284. }


复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-20 18:52

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表