二叉树:

二叉树(Binary tree)是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。二叉树特点是每个结点最多只能有两棵子树,且有左右之分

性质:

二叉树性质
性质1:二叉树的第i层上至多有2i-1(i≥1)个节点。
性质2:深度为h的二叉树中至多含有2h-1个节点。
性质3:若在任意一棵二叉树中,有n0个叶子节点,有n2个度为2的节点,则必有n0=n2+1。
性质4:具有n个节点的完全二叉树深为log2x+1(其中x表示不大于n的最大整数)。
性质5:若对一棵有n个节点的完全二叉树进行顺序编号(1≤i≤n),那么,对于编号为i(i≥1)的节点:
当i=1时,该节点为根,它无双亲节点。
当i>1时,该节点的双亲节点的编号为i/2。
若2i≤n,则有编号为2i的左节点,否则没有左节点。
若2i+1≤n,则有编号为2i+1的右节点,否则没有右节点。

输入:

运行结果:

代码:

/*朱海垅20300901112021年11月10日二叉链表实现二叉树
*/#include<iostream>
using namespace std;
template <class T>
struct BinTreeNode {T data;                                             //数据域BinTreeNode<T>* leftChiild, * rightChild;            //左右子域BinTreeNode() :leftChiild(NULL), rightChild(NULL) {}BinTreeNode(T x, BinTreeNode<T>* l = NULL, BinTreeNode<T>* r = NULL) :data(x), leftChiild(l), rightChild(r) {}
};
template<class T>
class BinaryTree {
public:BinaryTree() : root(NULL) {}                         //构造函数BinaryTree(T value) :RefValue(value), root(NULL) {}//构造函数BinaryTree(BinaryTree<T>& s) { root = Copy(s.root); }                     //复制构造函数~BinaryTree() { destory(root); }                                //析构函数bool IsEmpty() { return (root == NULL) ? true : false; }    //返回二叉树是否为空BinTreeNode<T>* Parent(BinaryTree<T>* current) { return (root == NULL || root = current) ? NULL : Parent(root, current); }    //返回父节点BinTreeNode<T>* LeftChild(BinTreeNode<T>* current) { return (current != NULL) ? current->leftChiild : NULL; }    //返回其节点的左子节点BinTreeNode<T>* RightChild(BinTreeNode<T>* current) { return (current != NULL) ? current->rightChild : NULL; }  //返回其节点的右子节点int Hight() { return Hight(root); }                         //返回树的高度(对数据进行封装)int NodeCount() { return NodeCount(root); }                  //返回树的节点数目(对数据进行封装)int LeafCount() { return LeafCount(root); }                    //返回树的叶子节点数(对数据进行封装)BinTreeNode<T>* GetRoot() const { return root; }            //返回根节点指针void preOrder(void(*vist)(BinTreeNode<T>* p)) { preOrder(root, vist); }//前序遍历void inOrder(void (*vist)(BinTreeNode<T>* p)) { inOrder(root, vist); }//中序遍历void postOrder(void(*vist)(BinTreeNode<T>* p)) { postOrder(root, vist); }//后序遍历/*void levelOrder(void(*vist)(BinTreeNode<T>* p)){Queue<BinTreeNode<T>*>Q;BinTreeNode<T>* p = root;Q.EnQueue(p);while (!Q.IsEmpty())        //队列不为空时{Q.DeQueue(p); visit(p);if (p->leftChiild != NULL)Q.EnQueue(p->leftChiild);if (p->rightChild != NULL)Q.EnQueue(p->rightChild);}}//层次序遍历(使用队列类实现简单)这里不列出队列类的构造*/protected:BinTreeNode<T>* root;                              //二叉树根指针T RefValue;                                         //数据输入停止标志void destory(BinTreeNode<T>*& subTree);                 //删除BinTreeNode<T>* Parent(BinTreeNode<T>* subTree, BinTreeNode<T>* current);//返回父节点int Hight(BinTreeNode<T>* subTree);                     //返回数的高度int NodeCount(BinTreeNode<T>* subTree);                   //返回树的节点数int LeafCount(BinTreeNode<T>* subtree);                      //返回树的叶子节点数void CreateBinTree(istream& in, BinTreeNode<T>*& subTree); //键盘输入建立树(用前序遍历输入)BinTreeNode<T>* Copy(BinTreeNode<T>* orignode);               //复制节点函数void Traverse(BinTreeNode<T>* subtree, ostream& out);         //前序遍历输出void Traverse1(BinTreeNode<T>* subtree, ostream& out);            //中序遍历输出void Traverse2(BinTreeNode<T>* subtree, ostream& out);            //后序遍历输出void preOrder(BinTreeNode<T>& subtree, void (*vist)(BinTreeNode<T>* p)){if (subtree != NULL)//递归结束条件为根空{vist(subtree);                         //访问根preOrder(subtree->leftChiild, vist);    //访问左子树preOrder(subtree->rightChild, vist);  //访问右子树 }}//前序遍历void inOrder(BinTreeNode<T>& subtree, void (*vist)(BinTreeNode<T>* p)){if (subtree != NULL){inOrder(subtree->leftChiild, vist);vist(subtree);inOrder(subtree->rightChild, vist);}}//中序遍历void postOrder(BinTreeNode<T>& subTree, void (*vist)(BinTreeNode<T>* p)){if (subTree != NULL){postOrder(subTree->leftChiild, vist);postOrder(subTree->rightChild, vist);vist(subTree);}}//后序遍历template <class T> friend istream& operator>>(istream& in, BinaryTree<T>& Tree);template <class T> friend ostream& operator<<(ostream& out, BinaryTree<T>& Tree);};
//删除
template<class T>
void BinaryTree<T>::destory(BinTreeNode<T>*& subTree)
{if (subTree != NULL){destory(subTree->leftChiild);destory(subTree->rightChild);             //递归删除节点delete subTree;}
}//返回父节点
template<class T>
BinTreeNode<T>* BinaryTree<T>::Parent(BinTreeNode<T>* subTree, BinTreeNode<T>* current)
{if (subTree == NULL)return NULL;if (subTree->leftChiild == current || subTree->rightChild == current)return subTree;BinTreeNode<T>* p;if ((p = Parent(subTree->leftChiild, current)) != NULL)return p;else return Parent(subTree->rightChild, current);
}//返回树高度
template <class T>
int BinaryTree<T>::Hight(BinTreeNode<T>* subtree)
{//递归求出树的高度if (subtree == NULL)return 0;else{int m = Hight(subtree->leftChiild);int n = Hight(subtree->rightChild);if (m > n)return (m + 1);else return (n + 1);//m,n,要么为1,要么为0.从树底往上叠加}
}//返回树节点数
template<class T>
int BinaryTree<T>::NodeCount(BinTreeNode<T>* subtree)
{if (subtree == NULL)return 0;else return NodeCount(subtree->leftChiild) + NodeCount(subtree->rightChild) + 1;//递归求出节点个数加一(根节点)
}//返回树叶子节点数目
template<class T>
int BinaryTree<T>::LeafCount(BinTreeNode<T>* subtree)
{if (!subtree)return 0;if (!subtree->leftChiild && !subtree->rightChild)return 1;//左右子树为空else return LeafCount(subtree->leftChiild) + LeafCount(subtree->rightChild);
}//前序遍历方法输入建立树,以此类推也可以用中序和和后序算法建立
template<class T>
void BinaryTree<T>::CreateBinTree(istream& in, BinTreeNode<T>*& subTree)
{T item;if (!in.eof())           //表示未读完,继续读取{cout << "请输入数据:" << endl;in >> item;if (item != RefValue){subTree = new BinTreeNode<T>(item);           //建立根节点if (subTree == NULL) { cout << "存储分配错误" << endl; exit(1); }cout << "请输入左树:" << endl;CreateBinTree(in, subTree->leftChiild);      //建立左子树cout << "请输入右树: " << endl;CreateBinTree(in, subTree->rightChild);        //建立右子树}else subTree = NULL;}
}//返回一个以orignode为根的二叉树副本
template<class T>
BinTreeNode<T>* BinaryTree<T>::Copy(BinTreeNode<T>* orignode)
{if (orignode == NULL)return NULL;BinTreeNode<T>* temp = new BinTreeNode<T>;temp->data = orignode->data;temp->leftChiild = Copy(orignode->leftChiild);temp->rightChild = Copy(orignode->rightChild);return temp;
}//搜索并输出根为subTree的二叉树(前序遍历输出)
template<class T>
void BinaryTree<T>::Traverse(BinTreeNode<T>* subTree, ostream& out)
{if (subTree != NULL)//是空则返回,否则一直输出到空{out << subTree->data << ' ';         //根Traverse(subTree->leftChiild, out);       //左Traverse(subTree->rightChild, out);       //右}
}//搜索并输出根为subTree的二叉树(中序遍历输出)
template<class T>
void BinaryTree<T>::Traverse1(BinTreeNode<T>* subTree, ostream& out)
{if (subTree != NULL)//是空则返回,否则一直输出到空{Traverse(subTree->leftChiild, out);        //左out << subTree->data << ' ';            //根Traverse(subTree->rightChild, out);       //右}
}//搜索并输出根为subTree的二叉树(后序遍历输出)
template<class T>
void BinaryTree<T>::Traverse2(BinTreeNode<T>* subTree, ostream& out)
{if (subTree != NULL)//是空则返回,否则一直输出到空{Traverse(subTree->leftChiild, out);        //左Traverse(subTree->rightChild, out);       //右out << subTree->data << ' ';            //根}
}//重载输入流操作,输入并建立一颗二叉树Tree
template<class T>
istream& operator>>(istream& in, BinaryTree<T>& Tree)
{Tree.CreateBinTree(in, Tree.root);return in;
}//重载输出操作,输出二叉树Tree
template<class T>
ostream& operator<<(ostream& out, BinaryTree<T>& Tree)
{out << "二叉树的前序遍历:" << endl;Tree.Traverse(Tree.root, out);//从根开始输出out << endl;out << "二叉树的中序遍历:" << endl;Tree.Traverse1(Tree.root, out);out << endl;out << "二叉树的后序遍历:" << endl;Tree.Traverse2(Tree.root, out);out << endl;return out;
}int main()
{char a='#';BinaryTree<char> A(a);     //默认构造函数以输入#为结束构造树cout << "输入”#“为构造函数结束" << endl;cout << "输入二叉树A:" << endl;cin >> A;char g = A.GetRoot()->data;cout << "根节点数据:     " << g << endl;int h = A.Hight();cout << "树高:     " << h << endl;int l = A.LeafCount();cout << "叶子节点数:       " << l << endl;cout << A;return 0;
}

ps:

部分知识点来自百度百科。

c++数据结构二叉树(二叉链表实现)基本操作实现相关推荐

  1. C#实现二叉树--二叉链表结构

    二叉树的简单介绍 关于二叉树的介绍请看这里 : 二叉树的简单介绍 http://www.cnblogs.com/JiYF/p/7048785.html 二叉链表存储结构: 二叉树的链式存储结构是指,用 ...

  2. 建立、遍历二叉树(二叉链表)

    建立二叉树: 由于先序.中序.后序遍历的任何一个遍历结果单独都不能唯一确定一颗二叉树,因此不能直接使用其中任何一个遍历结果来构造二叉树(原因是不能确定左右子树的大小(节点数),或者说不知道子树的结束位 ...

  3. 理论基础 —— 二叉树 —— 二叉链表

    [二叉链表] 二叉树一般采用二叉链表存储,其基本思想是:令二叉树的每个结点对应一个链表结点,链表结点除了存放与二叉树结点有关的数据信息外,还要设置指示左右孩子的指针. template<clas ...

  4. 6-2-二叉树(二叉链表存储)-树和二叉树-第6章-《数据结构》课本源码-严蔚敏吴伟民版...

    课本源码部分 第6章  树和二叉树 - 二叉树(二叉链表存储) --<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接☛☛☛ <数据结构-C语言版>(严蔚敏,吴 ...

  5. 数据结构C++边学边做--二叉树的实现(二叉链表实现遍历操作)

    二叉树的实现(二叉链表实现遍历操作) 一.二叉树的遍历 二.二叉链表的数据结构定义 三.二叉链表类实现 1.类声明 2.BiTree->构造函数:Create创建二叉链表 3.~BiTree-& ...

  6. 二叉链表-创建、遍历(前序、中序、后序、非递归、层次)、复制、计算深度、结点数、销毁(C语言)

    目录 二叉树的定义 二叉树的性质 二叉链表的基本操作 二叉链表的结构定义 前序遍历创建 前序.中序.后序遍历 中序遍历的非递归算法(栈) 层次遍历(队列) 复制二叉树 计算深度 计算总结点数与叶子结点 ...

  7. 二叉树的二叉链表表示与基本操作

    二叉树的二叉链表表示与基本操作(伪代码详细注释版,含源码) 一.二叉链表表示法 1. 二叉树 2. 二叉链表 二.二叉树的遍历(输出结点) 1. 层次遍历 2. 先序.中序.后序遍历(递归算法) 3. ...

  8. 数据结构-二叉链表存储的二叉树(利用先序遍历)

    树形结构是一类重要的非线性数据结构,其中以树和二叉树最为常用.对于每一个结点至多只有两课子树的一类树,称其为二叉树.二叉树的链式存储结构是一类重要的数据结构,其形式定义如下: 而二叉树的前序.中序遍历 ...

  9. 数据结构:(翻转二叉树) 若二叉树采用二叉链表作存储结构,要交换其所有分支结点的左右子树的位置,采用()遍历方法最合适

    题目 若二叉树采用二叉链表作存储结构,要交换其所有分支结点的左右子树的位置,采用()遍历方法最合适?(北京航空航天大学1999,北京工业大学2016) A. 前序 B. 中序 C. 后序 D. 层次 ...

最新文章

  1. Visual Studio c++必要的背景知识--链接与编译
  2. java·环境变量、基本数据类型
  3. 选项卡 都是显示在页面底部
  4. 定制Sublime主题
  5. with grant option mysql_mysql用户及权限(WITH GRANT OPTION)
  6. BTrace for Java应用程序简介
  7. 【转】DICOM:DICOM三大开源库对比分析之“数据加载”
  8. 【转】探索c#之Async、Await剖析
  9. datagridview设置为勾选才可编辑_使用lightroom前,做好这几项设置,有助于更好使用...
  10. mysql主从复制原理详解_简述 MySQL 逻辑架构与主从复制原理。
  11. data-packed volume container - 每天5分钟玩转 Docker 容器技术(43)
  12. EXPLAIN PLAN用法小议
  13. WRF-ChemV4.0安装
  14. Mac技巧1: 精确倍速QuickTime Player 播放器
  15. golang实现简单rpc调用
  16. 在信息流上,百度或许可以给谷歌信息流支个招
  17. 数据结构实验一,第10题:基于顺序存储结构的图书信息表的图书去重
  18. 链新:探索NFT中国化路径,与实体经济相结合
  19. mysql索引,索引结构,索引类型,索引失效
  20. STM32开发 | AD7606并行多路采集数据

热门文章

  1. 海外媒体推广,企业如何在YouTube做好海外网红KOL营销?
  2. Codeforces 939C - Convenient For Everybody
  3. IE 10 禁用多点触摸放大缩小页面
  4. Windows10忘记Microsoft账户密码桌面登录进不去,不重装系统删除微软账户更改本地用户登录
  5. JAVA入门学习 —方法使用
  6. 小白计算机视觉学习报告
  7. 网页设计色彩搭配原则
  8. 数据库-cmd下安装mysql服务
  9. RHEL6.9静默安装Oracle11204
  10. 3Q大战再起闪现“三英战吕布”?