c++学习笔记—二叉树基本操作的实现
用c++语言实现的二叉树基本操作,包括二叉树的创建、二叉树的遍历(包括前序、中序、后序递归和非递归算法)、求二叉树高度,计数叶子节点数、计数度为1的节点数等基本操作。
IDE:vs2013
具体实现代码如下:
- #include "stdafx.h"
- #include <malloc.h>
- #include <stack>
- #include <iostream>
- #define MAXSIZE 100
- using namespace std;
- typedef struct node //二叉树结构体
- {
- int data;
- struct node *lchild;
- struct node *rchild;
- }Bnode,*BTree;
- BTree CreateBinaryTree(BTree &tree){ //创建二叉树
- int inputdata;
- cin >> inputdata;
- if (-1 == inputdata)
- {
- tree = NULL;
- }
- else
- {
- if (!(tree = (Bnode*)malloc(sizeof(Bnode))))
- {
- cout<<"ERROR";
- }
- tree->data = inputdata;
- tree->lchild=CreateBinaryTree(tree->lchild);
- tree->rchild=CreateBinaryTree(tree->rchild);
- }
- return tree;
- }
- void preorderTraverse(BTree tree) //递归前序遍历
- {
- if (tree != NULL)
- {
- cout<<tree->data;
- }
- if (tree->lchild != NULL)
- {
- preorderTraverse(tree->lchild);
- }
- if (tree->rchild)
- {
- preorderTraverse(tree->rchild);
- }
- }
- void preorderTraverse2(BTree tree)
- {
- //////////////////////////////////////////////////////////////////////////
- // 非递归前序
- // 根据前序遍历访问的顺序,优先访问根结点,
- // 然后再分别访问左孩子和右孩子。
- // 即对于任一结点,其可看做是根结点,因此可以直接访问,访问完之后,
- // 若其左孩子不为空,按相同规则访问它的左子树;当访问其左子树时,
- // 再访问它的右子树。因此其处理过程如下:
- //
- //////////////////////////////////////////////////////////////////////////
- stack<BTree> s;
- if (!tree)
- {
- cout << "空树" << endl;
- return;
- }
- while (tree || !s.empty())
- {
- while (tree)
- {
- s.push(tree);
- cout << tree->data;
- tree = tree->lchild;
- }
- tree = s.top();
- s.pop();
- tree = tree->rchild;
- }
- }
- void inorderTraverse(BTree tree) //递归中序遍历
- {
- if (tree->lchild)
- {
- inorderTraverse(tree->lchild);
- }
- cout << tree->data;
- if (tree->rchild)
- {
- inorderTraverse(tree->rchild);
- }
- }
- void inorderTraverse2(BTree tree)
- {
- //////////////////////////////////////////////////////////////////////////
- // 非递归中序遍历
- // 根据中序遍历的顺序,对于任一结点,优先访问其左孩子,
- // 而左孩子结点又可以看做一根结点,然后继续访问其左孩子结点,
- // 直到遇到左孩子结点为空的结点才进行访问,
- // 然后按相同的规则访问其右子树。
- // 因此其处理过程如下:
- //
- ///////////////////////////////////////////////////////////////////////////
- stack<BTree> s;
- if (!tree)
- {
- cout << "空树" << endl;
- return;
- }
- while (tree || !s.empty())
- {
- while (tree)
- {
- s.push(tree);
- tree = tree->lchild;
- }
- tree = s.top();
- s.pop();
- cout << tree->data;
- tree = tree->rchild;
- }
- }
- void postoderTraverse(BTree tree) //递归后序遍历
- {
- if (tree->lchild)
- {
- postoderTraverse(tree->lchild);
- }
- if (tree->rchild)
- {
- postoderTraverse(tree->rchild);
- }
- cout << tree->data;
- }
- void postoderTraverse2(BTree tree)
- {
- //////////////////////////////////////////////////////////////////////////
- // 非递归后序遍历
- // 要保证根结点在左孩子和右孩子访问之后才能访问,
- // 因此对于任一结点P,先将其入栈。如果P不存在左孩子和右孩子,
- // 则可以直接访问它;或者P存在左孩子或者右孩子,
- // 但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。
- // 若非上述两种情况,则将P的右孩子和左孩子依次入栈,
- // 这样就保证了每次取栈顶元素的时候,左孩子在右孩子前面被访问,
- // 左孩子和右孩子都在根结点前面被访问。
- //////////////////////////////////////////////////////////////////////////
- stack<BTree> s;
- BTree cur; //当前结点
- BTree pre = NULL; //前一次访问的结点
- s.push(tree);
- while (!s.empty())
- {
- cur = s.top();
- if ((cur->lchild == NULL&&cur->rchild == NULL) ||(pre != NULL && (pre == cur->lchild || pre == cur->rchild)))
- {
- cout << cur->data; //如果当前结点没有孩子结点或者孩子节点都已被访问过
- s.pop();
- pre = cur;
- }
- else
- {
- if (cur->rchild != NULL)
- s.push(cur->rchild);
- if (cur->lchild != NULL)
- s.push(cur->lchild);
- }
- }
- }
- int Depth(BTree T) //求二叉树的深度
- {
- int dep = 0, depl, depr;
- if (!T) dep = 0;
- else
- {
- depl = Depth(T->lchild);
- depr = Depth(T->rchild);
- dep = 1 + (depl>depr ? depl : depr);
- }
- return dep;
- }
- int sumLeaf(BTree tree) //求叶子节点的个数
- {
- int sum = 0, m, n;
- if (tree)
- {
- if ((!tree->lchild) && (!tree->rchild))
- sum++;
- m = sumLeaf(tree->lchild);
- sum += m;
- n = sumLeaf(tree->rchild);
- sum += n;
- }
- return sum;
- }
- int numnSinglePoint(BTree tree ) //统计度为1的节点数目
- {
- int sum = 0, m, n;
- if (tree)
- {
- if ((tree->lchild!=NULL) && (tree->rchild == NULL))
- sum++;
- if ((tree->lchild == NULL) && (tree->rchild != NULL))
- sum++;
- m = numnSinglePoint(tree->lchild);
- sum += m;
- n = m = numnSinglePoint(tree->rchild);
- sum += n;
- }
- return sum;
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- BTree t;
- t= CreateBinaryTree(t);
- cout<<endl<<"非递归前序遍历:";
- preorderTraverse2(t);
- cout << endl<<"----------------------"<<endl;
- cout << "递归前序遍历:";
- preorderTraverse(t);
- cout << endl << "---------------------"<<endl;
- cout << "非递归中序遍历:";
- inorderTraverse2(t);
- cout << endl << "---------------------"<<endl;
- cout << "递归中序遍历:";
- inorderTraverse(t);
- cout << endl << "---------------------"<<endl;
- cout << "非递归后序遍历:";
- postoderTraverse2(t);
- cout << endl << "---------------------"<<endl;
- cout << "递归后序遍历:";
- postoderTraverse(t);
- cout << endl << "----------------------"<<endl;
- cout << "链表深度为:"<<Depth(t);
- cout << endl << "----------------------"<<endl;
- cout << "链表的叶子节点个数为:" << sumLeaf(t);
- cout << endl << "----------------------"<<endl;
- cout << "链表中度为1的节点数目为:" << numnSinglePoint(t) << endl;
- return 0;
- }
构建二叉树示意图为:
运行程序结果为:
c++学习笔记—二叉树基本操作的实现的更多相关文章
- 学习笔记——二叉树相关算法的实现(Java语言版)
二叉树遍历概念和算法 遍历(Traverse): 所谓遍历(Traversal)是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问. 从二叉树的递归定义可知,一棵非空的二叉树由根结点及左. ...
- 【Git/GitHub学习笔记】基本操作——创建仓库,本地、远程同步等
近日想分享一些文件,但是用度盘又太麻烦了(速度也很恶心).所以突发奇想去研究了下GitHub的仓库,这篇文章也就是一个最最最基础的基本操作.基本实现了可以在GitHub上存储文本信息与代码. 由于我的 ...
- saltstack学习笔记--grains基本操作
查看当前已经定义的监控项: [root@master ~]# salt "192.168.75.135" grains.items 192.168.75.135: ---- ...
- tensorflow学习笔记三----------基本操作
tensorflow中的一些操作和numpy中的很像,下面列出几个比较常见的操作 import tensorflow as tf #定义三行四列的零矩阵 tf.zeros([3,4]) #定义两行三列 ...
- SQL server2005学习笔记(一)数据库的基本知识、基本操作(分离、脱机、收缩、备份、还原、附加)和基本语法
在软件测试中,数据库是必备知识,假期闲里偷忙,整理了一点学习笔记,共同探讨. 阅读目录 基本知识 数据库发展史 数据库名词 SQL组成 基本操作 登录数据库操作 数据库远程连接操作 数据库分离操作 数 ...
- html5标签video(播放器)学习笔记(二)-基本操作
html5标签video(播放器)学习笔记(二)-基本操作 subying 发布时间: 2014/12/01 23:59 阅读: 13008 收藏: 21 点赞: 3 评论: 0 摘要 本文介绍了ht ...
- Kettle学习笔记(二)— 基本操作
目录 Kettle学习笔记(一)- 环境部署及运行 Kettle学习笔记(二)- 基本操作 kettle学习笔记(三)- 定时任务的脚本执行 Kettle学习笔记(四)- 总结 打开Kettle 打开 ...
- Django 学习笔记(七)数据库基本操作(增查改删)
一.前期准备工作,创建数据库以及数据表,详情点击<Django 学习笔记(六)MySQL配置> 1.创建一个项目 2.创建一个应用 3.更改settings.py 4.更改models.p ...
- 左偏树 / 非旋转treap学习笔记
背景 非旋转treap真的好久没有用过了... 左偏树由于之前学的时候没有写学习笔记, 学得也并不牢固. 所以打算写这么一篇学习笔记, 讲讲左偏树和非旋转treap. 左偏树 定义 左偏树(Lefti ...
随机推荐
- (笔记)Linux下查看CPU使用率的命令
1.top 使用权限:所有使用者 使用方式:top [-] [d delay] [q] [c] [S] [s] [i] [n] [b] 说明:即时显示process的动态 d :改变显示的更新速度,或 ...
- Python bytes decode() 方法
描述 bytes decode() 方法以指定的编码格式解码 bytes 对象,默认编码为 'utf-8'. 对应的编码方法:encode() 方法 . 语法 Python bytes decode( ...
- Python——signal
该模块为在Python中使用信号处理句柄提供支持.下面是一些使用信号和他们的句柄时需要注意的事项: 除了信号 SIGCHLD 的句柄遵从底层的实现外,专门针对一个信号的句柄一旦设置,除非被明确地重置, ...
- IE10弹窗showModalDialog关闭之后提示SCRIPT5011:不能执行已释放的Script代码
在Web开发中,经常使用showModalDialog弹窗 今天遇到一个小问题,IE10中弹窗关闭之后提示SCRIPT5011:不能执行已释放的Script代码 网上搜罗了一些资料,发现大多都提到对象 ...
- C# 之HTTP请求get,post带重试参数
public class WebHttp { /// <summary> /// get请求带重试 /// </summary> /// <param name=&quo ...
- Java VM
何时需要理解Java 虚拟机机制 一.排错 二.性能优化 字节码文件的执行流程.机制. 涉及到文件的加载机制(类加载器).执行机制(执行引擎).运行时优化(JIT运行时编译).以及内存分配与垃圾回收. ...
- 'AndroidManifest.xml' must have a minimum of 2 segments.
Manifest下必须有二级域名 <manifest xmlns:android="http://schemas.android.com/apk/res/android" p ...
- js pjax 和window.history.pushState,replaceState
原文:http://blog.linjunhalida.com/blog/pjax/ github:https://github.com/defunkt/jquery-pjax 什么是pjax? 现在 ...
- [mobile angular ui 1.2]桌面环境下如何自动隐藏左侧的sidebar?how to hide left sidebar on desktop browser by default?
使用mobile angular ui 1.2开发,在默认情况下,桌面浏览器中sidebar-left是默认打开的,怎么才能在程序初始打开时关闭sidebar-left呢? 目前我找到的唯一可行办法就 ...
- 用Lua实现string的trim()方法
function trim1(s) return (s:gsub("^%s*(.-)%s*$", "%1")) end -- from PiL2 20.4 fu ...