二叉树 的 存储与基本操作实现
2017-11-04 12:20
471 查看
数据结构课程学了二叉树,觉得自己大概理解了,但是实现还是总有困难,尤其是结构体指针这块,吃了不少亏
(一)存储与遍历(递归)
运行结果如下
(二)遍历、交换左右子树非递归实现
从难度上,中序遍历的非递归是最简单的,前序遍历居中,后序遍历最难
前序遍历
中序遍历
后序遍历
完整测试代码如下:
交换左右子树:
执行效果图:
(一)存储与遍历(递归)
#include<algorithm> #include<cstdlib> #include<cstdio> #include<queue> #include<stack> using namespace std; typedef struct BiTNode{ //定义结构体,包含数据域、左右子节点指针 int data; BiTNode *lchild,*rchild; }BiTNode,*BiTree; //定义一个BiTNode类型的结构体变量与结构体指针 //建立二叉树 void createBiTree(BiTree* t){ //此处必须为指针类型 int ch; scanf("%d",&ch); if(ch==-1){ //节点值输入为"-1"时,表示该节点没有左(右)叶节点 *t=NULL; } else{ *t=(BiTree)malloc(sizeof(BiTNode)); //开辟一块BiTree指针类型的空间 (*t)->data=ch; printf("请输入%d的左子节点值:",ch); createBiTree(&(*t)->lchild); //对地址进行操作,注意此格式 printf("请输入%d的右子节点值:",ch); createBiTree(&(*t)->rchild); } } //先序遍历(递归实现) void PreOrderTraverse(BiTree t){ if(t==NULL) return; else{ printf("%d",t->data); PreOrderTraverse(t->lchild); PreOrderTraverse(t->rchild); } } //中序遍历(递归实现) void InOrderTraverse(BiTree t){ if(t==NULL) return; else{ InOrderTraverse(t->lchild); printf("%d",t->data); InOrderTraverse(t->rchild); } } //后序遍历(非递归) void PostOrderTraverse(BiTree t){ if(t==NULL) return; else{ PostOrderTraverse(t->lchild); PostOrderTraverse(t->rchild); printf("%d",t->data); } } //求树深度 int deepth(BiTree t){ int deep=0; int ldeepth,rdeepth; if(t){ ldeepth=deepth(t->lchild); rdeepth=deepth(t->rchild); deep=ldeepth>=rdeepth?ldeepth+1:rdeepth+1; } return deep; } //交换左右子树(递归实现) void swapt(BiTree t){ BiTree temp; if(t==NULL) return; else{ temp=t->lchild; t->lchild=t->rchild; t->rchild=temp; swapt(t->lchild); swapt(t->rchild); } return; } int main(){ BiTree t; BiTree *p=(BiTree*)malloc(sizeof(BiTNode)); printf("请输入根节点的值:"); createBiTree(&t); printf("先序遍历该二叉树为:\n"); PreOrderTraverse(t); printf("\n"); printf("中序遍历输出为:\n"); InOrderTraverse(t); printf("\n"); printf("后序遍历输出为:\n"); PostOrderTraverse(t); printf("\n"); printf("树的深度为:%d\n",deepth(t)); printf("先序遍历输出交换左右子树后的二叉树:\n"); swapt(t); PreOrderTraverse(t); printf("\n"); return 0; }
运行结果如下
(二)遍历、交换左右子树非递归实现
从难度上,中序遍历的非递归是最简单的,前序遍历居中,后序遍历最难
前序遍历
//先序遍历(非递归) void PreOrderTraverse(BiTree root){ if(root==NULL) return; BiTree p=root; stack<BiTree> s; while(!s.empty()||p){ //遍打印边遍历,并存入栈中,以后需要借助这些根节点进入右子树 while(p){ printf("%d ",p->data); s.push(p); p=p->lchild; } //当p为非空时,说明根和左子树都遍历完了,该进入右子树了 if(!s.empty()){ p=s.top(); s.pop(); p=p->rchild; } } }
中序遍历
//中序遍历 void InOrderTraverse(BiTree root) { //空树 if(root==NULL) return; //树非空 BiTree p=root; stack<BiTree> s; while (!s.empty()||p){ //一直遍历到左子树最下边,边遍历边保存根节点到栈中 while(p){ s.push(p); p = p->lchild; } //当p为空时,说明已经到达左子树最下边,这时需要出栈了 if (!s.empty()){ p = s.top(); s.pop(); printf("%d ",p->data); //进入右子树,开始新的一轮左子树遍历(这是递归的自我实现) p=p->rchild; } } }
后序遍历
//后序遍历非递归 void PostOrderTraverse(BiTree root){ if(root==NULL) return; stack<BiTree> s; //pCur:当前访问节点,pLastVisit:上次访问节点 BiTree pCur,pLastVisit; pCur=root; pLastVisit =NULL; //先把pCur移动到左子树的最下边 while(pCur){ s.push(pCur); pCur=pCur->lchild; } while(!s.empty()){ //走到这里,pCur都是空,并已经遍历到左子树底端(看成扩充二叉树,则空,也是某科数的左孩子) pCur=s.top(); s.pop(); //一个根节点被访问的前提是:无右子树或右子树已被访问过 if(pCur->rchild==NULL||pCur->rchild==pLastVisit){ printf("%d ",pCur->data); //修改最近被访问的节点 pLastVisit=pCur; } // else{ //根节点再次入栈 s.push(pCur); //进入右子树,且可以肯定右子树一定不为空 pCur=pCur->rchild; while(pCur){ s.push(pCur); pCur=pCur->lchild; } } } printf("\n"); }
完整测试代码如下:
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<stack>
using namespace std;
typedef struct BiTNode{ //定义结构体,包含数据域、左右子节点指针
int data;
BiTNode *lchild,*rchild;
}BiTNode,*BiTree; //定义一个BiTNode类型的结构体变量与结构体指针
//建立二叉树
void createBiTree(BiTree* t){ //此处必须为指针类型
int ch;
scanf("%d",&ch);
if(ch==-1){ //节点值输入为"-1"时,表示该节点没有左(右)叶节点
*t=NULL;
}
else{
*t=(BiTree)malloc(sizeof(BiTNode)); //开辟一块BiTree指针类型的空间
(*t)->data=ch;
printf("请输入%d的左子节点值:",ch);
createBiTree(&(*t)->lchild); //对地址进行操作,注意此格式
printf("请输入%d的右子节点值:",ch);
createBiTree(&(*t)->rchild);
}
}
//先序遍历(非递归) void PreOrderTraverse(BiTree root){ if(root==NULL) return; BiTree p=root; stack<BiTree> s; while(!s.empty()||p){ //遍打印边遍历,并存入栈中,以后需要借助这些根节点进入右子树 while(p){ printf("%d ",p->data); s.push(p); p=p->lchild; } //当p为非空时,说明根和左子树都遍历完了,该进入右子树了 if(!s.empty()){ p=s.top(); s.pop(); p=p->rchild; } } }
//中序遍历 void InOrderTraverse(BiTree root) { //空树 if(root==NULL) return; //树非空 BiTree p=root; stack<BiTree> s; while (!s.empty()||p){ //一直遍历到左子树最下边,边遍历边保存根节点到栈中 while(p){ s.push(p); p = p->lchild; } //当p为空时,说明已经到达左子树最下边,这时需要出栈了 if (!s.empty()){ p = s.top(); s.pop(); printf("%d ",p->data); //进入右子树,开始新的一轮左子树遍历(这是递归的自我实现) p=p->rchild; } } }
//后序遍历非递归
void PostOrderTraverse(BiTree root){
if(root==NULL)
return;
stack<BiTree> s;
//pCur:当前访问节点,pLastVisit:上次访问节点
BiTree pCur,pLastVisit;
pCur=root;
pLastVisit =NULL;
//先把pCur移动到左子树的最下边
while(pCur){
s.push(pCur);
pCur=pCur->lchild;
}
while(!s.empty()){
//走到这里,pCur都是空,并已经遍历到左子树底端(看成扩充二叉树,则空,也是某科数的左孩子)
pCur=s.top();
s.pop();
//一个根节点被访问的前提是:无右子树或右子树已被访问过
if(pCur->rchild==NULL||pCur->rchild==pLastVisit){
printf("%d ",pCur->data);
//修改最近被访问的节点
pLastVisit=pCur;
}
//
else{
//根节点再次入栈
s.push(pCur);
//进入右子树,且可以肯定右子树一定不为空
pCur=pCur->rchild;
while(pCur){
s.push(pCur);
pCur=pCur-&
4000
gt;lchild;
}
}
}
printf("\n");
}
int main(){
// freopen("input11.txt","r",stdin);
BiTree t;
BiTree *p=(BiTree*)malloc(sizeof(BiTNode));
printf("请输入根节点的值:");
createBiTree(&t);
printf("\n");
printf("先序遍历该二叉树为:\n");
PreOrderTraverse(t);
printf("\n");
printf("中序遍历输出为:\n");
InOrderTraverse(t);
printf("\n");
printf("后序遍历输出为:\n");
PostOrderTraverse(t);
return 0;
}
交换左右子树:
void Exchange(BiTree bt){ queue<BiTree> q; BiTree p; if(bt!=NULL){ q.push(bt); } while(!q.empty()){ BiTree p=q.front(); q.pop(); //出队 if(p->lchild!=NULL){ q.push(p->lchild); } if(p->rchild!=NULL){ q.push(p->rchild); } BiTree temp; temp=p->lchild; p->lchild=p->rchild; p->rchild=temp; } return; }
执行效果图:
相关文章推荐
- 使用C++链表来实现二叉树的存储和基本操作
- 二叉树基本操作实现(二叉树的链式存储)
- 二叉树(二叉链式存储)8种基本操作的实现
- 二叉树基本操作实现(二叉树的顺序存储)
- c语言实现二叉树的基本操作--二叉链表存储
- 使用C++数组实现二叉树的存储和基本操作
- javascript实现数据结构: 树和二叉树,二叉树的遍历和基本操作
- 南邮数据结构实验二---二叉树的基本操作及哈夫曼编码译码系统的实现
- 八.二叉树各种操作的C语言实现 树的一些基本的操作,包括,树的建立,树的深度,
- 【 数据结构】实现二叉树以及其基本操作
- 二叉树学习(二):二叉树的基本操作及代码实现
- 第4章第3节 二叉树的基本操作(非递归实现)
- 数据结构——排序/搜索二叉树(非递归)的基本操作实现
- 数据结构.二叉树的基本操作(C语言实现)
- 二叉树基本操作的程序实现
- C语言实现二叉树的基本操作---创建、遍历、求深度、求叶子结点
- 二叉树的基本操作实现
- c++模板实现二叉树,线索化,线索化遍历,非递归遍历及一些基本操作
- 【Java】实现二叉树基本操作、面试题
- 数据结构 — 二叉树的基本操作实现(递归算法)