二叉树的初步实现
二叉树的初步实现,写了有一段时间了,如果有大神发现不足之处,希望可以帮我指出来,感激不尽!、
二叉树(Binary Tree)是一种树形结构,它的特点是每个结点至多只有两颗子树(即二叉树中不存在大于2的结点),并且,二叉树的子树有左右之分,其次序不能任意改变。
根据二叉树的性质,我们可以将二叉树的每一个结点的结构画出来:
代码实现:
class BinaryTreeNode { public: ElemType content; //结点中的元素 BinaryTreeNode *leftnode; //指向左子树的结点 BinaryTreeNode *rightnode; //指向右子树的结点 };
二叉树的结构:
创建二叉树:
创建二叉树的思路是,输入值,如果不为-1,那么先为当前结点内的content赋值,再次输入值,如果值不为-1,那么为当前结点的左子树赋值,如果为-1,那么为根节点的右子树赋值,好吧,可能有点乱,画个图就好了。
比如说输入的值是:1 2 -1 3 -1 -1 4 -1 -1
那么,得到的二叉树的结构就是:
对于这种输入,我们可以用递归的思想,这种思想类似于二叉树的前序遍历,这个后面会说到。
代码实现:
void CreatBinaryTree(BinaryTreeNode*&head) { //------首先判断输入的内容是否为-1,如果为-1那么返回上一层 //临时变量,用来储存输入的内容 ElemType linshi; cout << "请输入值:"; cin >> linshi; if (linshi == -1) { //如果输入的是-1号,那么当前指针指向空参数 head = NULL; } //如果输入的不是-1号,那么,做相应的操作 else { //为当前head指针创建新的结点 head = new BinaryTreeNode; //为当前结点的内容赋值 head->content = linshi; //用当前左儿子的结点作参数,再次调用CreatBinaryTree()函数 CreatBinaryTree(head->leftnode); //用当前右儿子的结点做参数,再次调用CreatBianryTree()函数 CreatBinaryTree(head->rightnode); } }
关于输入这里呢,用了递归的思路,可能有些同学会不太懂,因此,我决定在这里对上面的代码进行分析,帮助同学们对递归有更好的理解:
好吧,这个图我画了半个小时.......
那么,懂了吧!懂了的话,就说明,你已经对前序遍历理解啦,接下来,中序和后序遍历理解的就很快啦!我就能不画图啦!😀
那么,接下来开始说前序遍历,先放代码!
//输出二叉树结点,利用递归,先序遍历 void PreorderTraversal(BinaryTreeNode*head) { if (head == NULL) return; else { //输出当前结点 cout << head->content << " "; //以当前结点的左结点为参数,再次调用PrintBinaryTree()函数 PreorderTraversal(head->leftnode); //以当前结点的右结点为参数,再次调用PrintBinaryTree()函数 PreorderTraversal(head->rightnode); } }
有没有一种似曾相识的感觉?你可以向上翻一下,上面的输入中的else中的代码是不是和这个很相似!因为他们是一个思路啊,兄得!
那么,这里就不多说啦(因为我懒得画图了...),前序遍历输出的顺序是:1 2 3 4
那么,接下来就是中序遍历,上代码!
//输出二叉树结点,利用递归,中序遍历 void InorderTraversal(BinaryTreeNode*head) { if (head == NULL) return; else { //以当前结点的左结点为参数,调用InorderTraversal()函数 InorderTraversal(head->leftnode); //输出当前结点的内容 cout << head->content << " "; //以当前结点的右结点为参数,调用InorderTraversal()函数 InorderTraversal(head->rightnode); } }
怎么样,是不是又有一种似曾相识的感觉,你可以向上翻一下前序遍历的代码,他们的区别就在于,输出元素的时间不一样,前序的在最前面,中序的在中间,那么,后序的
你肯定就会了吧!自己试一下吧!
中序遍历输出:2 3 1 4
后序遍历输出:3 2 4 1
对啦,这里说一个小的知识点,我们可以根据两种输出的结果,推出唯一的一颗二叉树,前提是,两种输出结果中,有一种是中序遍历!那么好啦,终于写完啦!
放出全部代码!
//本程序的目的是利用链表实现二叉树,并且实现先序遍历,中序遍历,后序遍历 #include<iostream> using namespace std; //二叉树的结点 template<class T> class BinaryTreeNode { public: BinaryTreeNode<T>* leftnode; //左边的结点 BinaryTreeNode<T>* rightnode; //右边的结点 T content; //结点中内容 }; //创建二叉树,利用递归从左到右创建,如果输入-1则表示该结点为空 //创建二叉树函数的模块的思路是在csdn上找到的思路,利用递归函数创建,//先序的思路 template<class T> void PreCreatBinaryTree(BinaryTreeNode<T>*&head) { //------首先判断输入的内容是否为-1,如果为-1那么返回上一层 //临时变量,用来储存输入的内容 T linshi; cout << "请输入值:"; cin >> linshi; if (linshi == -1) { //如果输入的是-1号,那么当前指针指向空参数 head = NULL; } //如果输入的不是-1号,那么,做相应的操作 else { //为当前head指针创建新的结点 head = new BinaryTreeNode<T>; //为当前结点的内容赋值 head->content = linshi; //用当前左儿子的结点作参数,再次调用CreatBinaryTree()函数 CreatBinaryTree(head->leftnode); //用当前右儿子的结点做参数,再次调用CreatBianryTree()函数 CreatBinaryTree(head->rightnode); } } //输出二叉树结点,利用递归,先序遍历 template<class T> void PreorderTraversal(BinaryTreeNode<T>*head) { if (head == NULL) return; else { //输出当前结点 cout << head->content << " "; //以当前结点的左结点为参数,再次调用PrintBinaryTree()函数 PreorderTraversal(head->leftnode); //以当前结点的右结点为参数,再次调用PrintBinaryTree()函数 PreorderTraversal(head->rightnode); } } //输出二叉树结点,利用递归,中序遍历 template<class T> void InorderTraversal(BinaryTreeNode<T>*head) { if (head == NULL) return; else { //以当前结点的左结点为参数,调用InorderTraversal()函数 InorderTraversal(head->leftnode); //输出当前结点的内容 cout << head->content << " "; //以当前结点的右结点为参数,调用InorderTraversal()函数 InorderTraversal(head->rightnode); } } //输出二叉树结点,利用递归,后序遍历 template<class T> void PostorderTraversal(BinaryTreeNode<T>*head) { //如果结点为空,返回上一层 if (head == NULL) return; //如果不为空,执行相应的操作 else { //以当前结点的左结点为参数,调用PostorderTraversal()函数 PostorderTraversal(head->leftnode); //以当前结点的右结点为参数,调用PostorderTraversal()函数 PostorderTraversal(head->rightnode); //输出当前结点的内容 cout << head->content << " "; } } //销毁二叉树,利用递归,后序遍历(销毁是用后序遍历,如果用先序遍历或者中序遍历会使树断掉) //关于销毁二叉树的函数让我十分惊喜,因为,他可以将头节点一并删除 template<class T> void DestoryBinaryTree(BinaryTreeNode<T>* &head) { //如果结点为空,返回上一层结点 if (head == NULL) return; //如果结点不为空,执行相应操作 else { //调试信息 BinaryTreeNode<int>*head1 = head; //以当前结点的左结点为参数,调用DestoryBinaryTree()函数 DestoryBinaryTree(head->leftnode); //以当前结点的右结点为参数,调用DestoryBinaryTree()函数 DestoryBinaryTree(head->rightnode); //销毁当前结点 delete head; } } //主函数 int main() { BinaryTreeNode <int>*a = new BinaryTreeNode<int>; PostCreatBinaryTree(a); cout << "先序输出:"; PreorderTraversal<int>(a); cout << endl; cout << "中序输出:"; InorderTraversal<int>(a); cout << endl; cout << "后序输出:"; PostorderTraversal<int>(a); cout << endl; //销毁二叉树 DestoryBinaryTree<int>(a); //销毁新创建的二叉树结点 //delete a; system("pause"); return 0; }