二叉树的基本操作(总结)
来源:互联网 发布:最新营销软件 编辑:程序博客网 时间:2024/05/16 09:00
二叉树的基本操作
二叉树的定义决定了其大多数操作都可以由递归去实现
本文通过递归和非递归两种方式实现二叉树的基本操作(加深对原理的理解)
1.二叉树的声明
typedef char ElementType; typedef struct TreeNode* BinTree;struct TreeNode{ ElementType Data; struct TreeNode* Left; struct TreeNode* Right;};
2.遍历
(1)递归实现
>1 先序遍历
按照“根节点-左儿子-右儿子”的顺序访问
void PreorderTraversal(BinTree BT) {if (!BT) return; //空树,直接返回visit(BT->Data);PreorderTraversal(BT->Left); //递归遍历左子树PreorderTraversal(BT->Right); //递归遍历右子树}
>2 中序遍历
按照“左儿子-根节点-右儿子”的顺序访问
void InorderTraversal(BinTree BT){ if(!BT) return ; InorderTraversal(BT->Left); visit(BT->Data); InorderTraversal(BT->Right);}
>3 后序遍历
按照“左儿子-右儿子-根节点”的顺序访问
void PostorderTraversal(BinTree BT){ if(!BT) return ; InorderTraversal(BT->Left); InorderTraversal(BT->Right); visit(BT->Data);}
(2)非递归实现(二叉树的非递归实现借助栈来实现)
属于哪种遍历取决于根节点第几次遇到时访问
>1 先序遍历(首次遇到时访问)
//C语言实现int MaxSize = 1000;void PreorderTraversalRecur(BinTree BT) { TreeNode* St[MaxSize], *p;//创建一个栈int top = -1;//top的下一个位置指向栈顶if (!BT) {St[++top] = BT;//根节点入栈while (top > -1) {p = St[top];top--;printf("%c ", p->Data);//先序遍历,第一次遇到(入栈)时就访问//左右子树压栈if (!p->Left) St[++top] = p->Left;if (!p->Right) St[++top] = p->Right;}}}
//C++实现void PreOrderTraversal(BinTree BT) {if (!BT) return;stack<BinTree> s;BinTree temp;s.push(BT);while (!s.empty()) {temp = s.top();printf("%c ", temp->Data);s.pop();if (temp->Left)s.push(temp->Left);if (temp->Right)s.push(temp->Right);}}
>2 中序遍历
void InorderTraversal(BinTree BT) {TreeNode *St[MaxSize], *node;int top = -1;if (!BT) {node = BT;while (top > -1 || node != NULL) {//先把所有的左子树压栈while (node != NULL) {St[++top] = node;node = node->Left;}//回溯,访问最后入栈的结点的右子树if (top > -1) {node = St[top--];//取除栈顶元素,并且top--printf("%c ", node->Data);//此时第二次遇到根节点,访问node = node->Right;}}}}
void InOrderTravel(BinTree BT) {if (!BT) return;stack<BinTree> s;BinTree node = BT;while (!node || !s.empty()) {while (!s.empty() || node) {//一直遍历到左子树最下边,边遍历边保存根节点到栈中 while (node) {s.push(node);node = node->Left;}//当p为空时,说明已经到达左子树最下边,这时需要出栈了 if (!s.empty()) {node = s.top();s.pop();printf("%c ", node->Data);//进入右子树,开始新的一轮左子树遍历(这是递归的自我实现) node = node->Right;}}/*//另解while (!s.empty() || node) {if (node) {s.push(node);node = node->Left;}else {node = s.top();s.pop();printf("%c ", node->Data);node = node->Right;}}*/}}
>3 后序遍历
//C++实现void PostorderTraversalRecursion(BinTree BT) {if (!BT)return;stack<BinTree> s;//pCur:当前访问节点,pLast:上次访问节点 BinTree pCur, pLast;pCur = BT;pLast = NULL;//把左子树结点全部压栈while (pCur) {s.push(pCur);pCur = pCur->Left;}//已经遍历到左子树底端while (!s.empty()) {pCur = s.top();s.pop();if (pCur->Left == pLast) {//若左子树刚被访问过,则需先进入右子树(根节点需再次入栈)//根节点再次入栈 s.push(pCur);//进入右子树,且可肯定右子树一定不为空 pCur = pCur->Right;while (pCur) {s.push(pCur);pCur = pCur->Right;}}//一个根节点被访问的前提是:无右子树或右子树已被访问过 else if (pCur->Right == NULL || pCur->Right == pLast) {printf("%c ", pCur->Data);//修改最近被访问的节点 pLast = pCur;}}}
参考:http://blog.csdn.net/zhangxiangdavaid/article/details/37115355
层序遍历(利用队列实现)
>1 C语言实现队列
void LevelorderTraversal(BinTree BT) {BinTree q[1000];BinTree temp;int head = 0, tail = 0;if (!BT) return;else {q[tail++] = BT;while (tail != head) {temp = q[head++];printf(" %c", temp->Data);if (temp->Left) q[tail++] = temp->Left;if (temp->Right) q[tail++] = temp->Right;}}}
2> C++(queue)实现
void LevelorderTraversal(BinTree BT) {queue <BinTree> q;BinTree temp;if (!BT) return;else {q.push(BT);//根节点入队while (!q.empty()) {temp = q.front();q.pop();//队首元素出队,并访问cout << temp->Data << ' ';if (temp->Left) q.push(temp->Left);//左儿子入队if (temp->Right) q.push(temp->Right);//右儿子入队}}}
3.其他操作
(1)求树的高度
int GetHeight(BinTree BT) {/*if (BT == NULL)return 0;else return 1 +(GetHeight(BT->Left) > GetHeight(BT->Right) ? GetHeight(BT->Left): GetHeight(BT->Right)); */ int h = 0;if (BT == NULL) {return 0;}int lh = GetHeight(BT->Left) + 1;int rh = GetHeight(BT->Right) + 1;h = lh > rh ? lh : rh;return h;}
(2)求二叉树结点的个数
int Nodenum(BinTree BT) { if(!BT) return 0; else return 1+Nodenum(BT->Left)+Nodenum(BT->Right); }
(3)求叶子结点的个数
int LeavesCount(BiTree BT) { if(!BT == NULL) return 0; //BT为空树,返回0 int cnt = 0; if(!(BT->LChild || BT->RChild)) ++cnt; //BT为叶子结点,加1 else { //递归求左子树上的叶子结点,并累加 cnt += LeavesCount(BT->LChild); //递归求右子树上的叶子结点,并累加 cnt += LeavesCount(BT->RChild); } return cnt; }
本人才疏学浅,如有错误,欢迎大家指正
阅读全文
0 0
- 二叉树的基本操作(总结)
- 树(二叉树)的基本操作
- 二叉树的基本操作(C++)
- 二叉树的基本操作(二)
- 二叉树的基本操作(二)
- 二叉树的基本操作(递归)
- 二叉树的基本操作(1)
- 二叉树的基本操作(严蔚敏)
- (数据结构)二叉树的基本操作
- 二叉树的基本操作
- 二叉树的基本操作
- 二叉树的基本操作
- 二叉树的基本操作
- 二叉树的基本操作
- 二叉树的基本操作
- 二叉树的基本操作
- 二叉树的基本操作
- 二叉树的基本操作
- random.shuffle的使用
- vue + webpack 构建项目
- React-native 学习之AlertDialog弹出框
- adb命令不常用
- [leetcode]#67. Add Binary
- 二叉树的基本操作(总结)
- 【2】在Ubuntu上为Android系统内置C可执行程序测试Linux内核驱动程序
- noip2017(AFO)游记
- leetcode 233. Number of Digit One
- Samba服务器搭建(Linux)
- c#之上下滚动播放
- 【我的Java笔记】异常类
- 【Unity学习笔记】关于在Unity中build apk error
- ubuntu17.10笔记本待机后无法唤醒的解决方案