关于二叉树的相关操作汇总,其中包含以下操作:
- 递归前序遍历
- 非递归前序遍历
- 递归中序遍历
- 非递归中序遍历
- 递归后序遍历
- 非递归后序遍历
- 递归层次遍历
- 非递归层次遍历
- 递归计算二叉树的高度
- 非递归计算二叉树高度
- 递归查找某点在二叉树的那一层
- 非递归查找某点在二叉树的那一层
- 判断两棵二叉树是否相似
- 判断二叉树是不是完全二叉树
- 输出某一结点的到跟结点的路径
- 得到两个结点的最近的共同祖先
- 拆分二叉树
- 统计二叉树的结点个数
- 线索中序二叉树的建立
- 线索中序二叉树的输出
- 根据前序和中序非递归建立二叉树
- 根据前序和中序递归建立二叉树
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX_SIZE 100
typedef struct BiTNode{
char data;
struct BiTNode *lchild, *rchild;
}BiTNode,*BiTree;
typedef struct BiTNodeTag{
BiTNode *btnode;
int tag;
}BiTNodeTag;
typedef struct BiThrNode{
char data;
struct BiThrNode *lchild, *rchild;
int ltag,rtag;
}BiThrNode;
BiTNode *mallocTreeNode(char p){
BiTNode *temp = (BiTNode *) malloc(sizeof(BiTNode));
temp->data = p;
temp ->lchild = NULL;
temp->rchild = NULL;
return temp;
}
void printNodeData(BiTNode *nod){
printf("%c",nod->data);
}
//递归建立二叉树
void createBiTree(BiTree &t){
char ch;
scanf("%c",&ch);
if (ch == ' '){
t = NULL;
return;
}
if (!(t = (BiTree)malloc(sizeof(BiTNode)))){
exit(1);
}
t->data = ch;
printf("the data is %c\n",ch);
createBiTree(t->lchild);
createBiTree(t->rchild);
}
//非递归建立二叉树
BiTNode *createBiTree(){
//char str[] ="ABC@G@@@DE@@F@I";
//char str[] ="ABC@G@@@DE@@@";
//char str[] ="ABJK@@IC@G@@@";
char str[] ="ABC@G@@@DE@@@";
//char str[] ="ABC@G@@";
//char str[] ="A@B@";
//char str[] ="AB@@C@";
//char str[] ="A@B@C@";
char *p = str;
BiTNode * stack[MAX_SIZE];
int top = -1;
BiTNode *pTree = NULL;
BiTNode *rootNode = NULL;
int isRightTree = 0;
if (*p == '@'){
printf("空二叉树");
exit(0);
}
//根节点入栈
pTree = mallocTreeNode(*p);
p++;
stack[++top] = pTree;
rootNode = pTree;
while (*p){
if (*p != '@'){
if (isRightTree){
BiTNode *temp = mallocTreeNode(*p);
pTree->rchild = temp;
pTree = temp;
//入栈
stack[++top] = pTree;
//因为每次只能执行一次向右插入操作
isRightTree = 0;
} else {
BiTNode *temp = mallocTreeNode(*p);
pTree->lchild = temp;
pTree = temp;
//入栈
stack[++top] = pTree;
}
} else {
if (top == -1){
break;
} else {
pTree = stack[top--];
}
if (!isRightTree){
//等于@时退栈,同时向右子树插入
isRightTree = 1;
}
}
p++;
}
return rootNode;
}
//递归前序遍历
void preOrderTraverse(BiTree t){
if (t!= NULL){
printNodeData(t);
preOrderTraverse(t->lchild);
preOrderTraverse(t->rchild);
}
}
//非递归前序遍历1
void preOrderTraverse1(BiTree t){
BiTNode *stack[MAX_SIZE];
int top = -1;
printNodeData(t);
BiTNode* temp = t;
stack[++top] = t;
t = t->lchild;
while(top > -1){
if (t != NULL){
printNodeData(t);
stack[++top] = t;
t = t->lchild;
}else{
//退栈操作的原因:左子树为空,右子树为空,在左子树为空时,直接进入退栈程序,退到上层之后访问右子树。
//在右子树为空时,说明本层的程序已经完成操作,需要退到上层继续进行操作。
//这时候就考虑是访问左子树还是右子树,因为程序本身是访问了左子树之后进栈的,因此退栈后应访问右子树。
t = stack[top--];
//当出栈的结点为头结点时,因为头结点退栈之后,整个栈就为空了。因此需要判断。
if (temp == t){
t = t->rchild;
//判断右子树是否为空。
if (t != NULL){
//不为空,则进栈
stack[++top] = t;
continue;
} else{
//为空,结束循环
break;
}
}
t = t->rchild;
}
}
}
//非递归前序遍历2
void preOrderTraverse2(BiTree p){
BiTNode *stack[MAX_SIZE];
int top = -1;
//将栈值和当前结点一起判断,简化了前一个方法。
while(top > -1 || p != NULL){
if (p != NULL){
printNodeData(p);
stack[++top] = p;
p = p->lchild;
} else {
p = stack[top--];
p = p->rchild;
}
}
}
//非递归前序遍历3
void preOrderTraverse3(BiTree p){
BiTNode *stack[MAX_SIZE];
int top = -1;
stack[++top] = p;
while(top >-1){
p = stack[top--];
printNodeData(p);
if(p->rchild != NULL){
stack[++top] = p->rchild;
}
if(p->lchild != NULL){
stack[++top] = p->lchild;
}
}
}
//递归中序遍历
void inOrderTraverse(BiTree t){
if (t != NULL){
inOrderTraverse(t->lchild);
printNodeData(t);
inOrderTraverse(t->rchild);
}
}
//非递归中序遍历
void inOrderTraverse1(BiTree t){
BiTNode *stack[MAX_SIZE];
int top = -1;
BiTNode * temp = t;
while(top > -1 || t != NULL){
while(t != NULL){
stack[++top] = t;
t = t->lchild;
}
t = stack[top--];
printNodeData(t);
t = t->rchild;
}
}
//递归后序遍历
void postOrderTraverse(BiTree t){
if (t != NULL){
postOrderTraverse(t->lchild);
postOrderTraverse(t->rchild);
printNodeData(t);
}
}
//非递归后序遍历1,每个结点加一个标志位,表示该结点是第几次在栈顶。如果是第二次则可以输出了。如果不是,则需要访问其右子树。
/************************************************************************/
/* 对于任一结点P,将其入栈,然后沿其左子树一直往下搜索,直到搜索到没有左孩子的结点,此时该结点出现在栈顶,但是此时不能将其出栈并访问,因此其右孩子还为被访问。所以接下来按照相同的规则对其右子树进行相同的处理,当访问完其右孩子时,该结点又出现在栈顶,此时可以将其出栈并访问。这样就保证了正确的访问顺序。可以看出,在这个过程中,每个结点都两次出现在栈顶,只有在第二次出现在栈顶时,才能访问它。因此需要多设置一个变量标识该结点是否是第一次出现在栈顶。 */
/************************************************************************/
void postOrderTraverse1(BiTree p){
BiTNodeTag *stack[MAX_SIZE];
int top = -1;
while(top > -1 || p != NULL){
while(p != NULL){
BiTNodeTag *btn=(BiTNodeTag *)malloc(sizeof(BiTNodeTag));
btn->btnode = p;
btn->tag = 1;
stack[++top]= btn;
p = p->lchild;
}
if (top >-1){
if (stack[top]->tag ==1 ){
p = stack[top]->btnode;
stack[top]->tag = 2;
p = p->rchild;
} else{
p = stack[top--]->btnode;
printNodeData(p);
//因为要退栈,所以这里必须要置为空
p=NULL;
}
}
}
}
void postOrderTraverse2(BiTree p){
BiTNodeTag stack[MAX_SIZE];
int top = -1;
while(top > -1 || p != NULL){
while(p != NULL){
top++;
stack[top].btnode = p;
stack[top].tag = 1;
p = p->lchild;
}
if (top >-1){
if (stack[top].tag ==1 ){
p = stack[top].btnode;
stack[top].tag = 2;
p = p->rchild;
} else{
p = stack[top--].btnode;
printNodeData(p);
//因为要退栈,所以这里必须要置为空
p=NULL;
}
}
}
}
/************************************************************************/
/* 根据特点访问。。。要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,先将其入栈。如果P不存在左孩子和右孩子,则可以直接访问它;或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。若非上述两种情况,则将P的右孩子和左孩子依次入栈,这样就保证了每次取栈顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。 */
/************************************************************************/
void postOrderTraverse3(BiTree p){
BiTNode *stack[MAX_SIZE];
int top = -1;
stack[++top] = p;//根节点入栈
BiTNode * pre = NULL; //用于记录上次访问结点
BiTNode * cur = NULL;
while(top >-1){
cur = stack[top];
if ((cur->lchild == NULL && cur->rchild == NULL )||(pre!= NULL &&(pre == cur->rchild || pre == cur->lchild))){
printNodeData(cur);
//访问过之后,将这个结点移除
top--;
pre = cur;
} else {
if(cur->rchild != NULL){
stack[++top] = cur->rchild;
}
if(cur->lchild != NULL){
stack[++top] = cur->lchild;
}
}
}
}
//非递归后序遍历。。 最优方法
void postOrderTraverse4(BiTree p){
BiTNode *stack[MAX_SIZE];
int top = -1;
stack[++top] = p;
p = p->lchild;
BiTNode *pre = NULL;//之前的一个结点
while (top > -1){
//访问左子树
while(p != NULL){
stack[++top] = p;
p = p->lchild;
}
//每次都要将其置为空
pre = NULL;
//这里使用while而不使用if的原因是,
//如果使用if证明以下语句至多执行一次,而栈中有多个左子树的结点已经访问过。而其右子树(多个结点)没有访问过。
while (top>-1){
p = stack[top];
//因为如果pre == p->rchild即前一个结点等于当前结点的右结点,证明,当前结点的左子树已经输出,而且其右子树也已经输出,则本结点可以输出。
//第一个输出的是根节点
if (pre == p->rchild){
top--;
printNodeData(p);
pre = p;
}else {
//如果不是,则访问右子树。
p = p->rchild;
break;
}
}
}
}
BiTNode *queue[MAX_SIZE];
int front= 0, rear = 0;
//递归层次遍历,使用队列
void levelOrderTraverse(BiTree p){
if (p == NULL){
return;
}
printNodeData(p);
if ( p->lchild != NULL){
queue[rear++] = p->lchild;
}
if ( p->rchild != NULL){
queue[rear++] = p->rchild;
}
p = queue[front++];
levelOrderTraverse(p);
}
void printDataByLevel(BiTNode *p, int i,int n);
int countLevelOfBiTree2(BiTree p);
//按照层次遍历,不使用队列
void levelOrderTraverse1(BiTree p){
int level = countLevelOfBiTree2(p);
int i = 1 ;
for (i= 1;i<=level;i++){
printDataByLevel(p,i,1);
}
}
//按照层次打印
void printDataByLevel(BiTNode *p, int i,int n){
if (p == NULL){
return;
}
if (i == n){
printNodeData(p);
}
printDataByLevel(p->lchild,i,n+1);
printDataByLevel(p->rchild,i,n+1);
}
//非递归层次遍历
void levelOrderTraverse2(BiTree p){
BiTNode *queue[MAX_SIZE];
int front= 0, rear = 0;
queue[rear++] = p;
while(front != rear){
p = queue[front++];
printNodeData(p);
if ( p->lchild != NULL){
queue[rear++] = p->lchild;
}
if ( p->rchild != NULL){
queue[rear++] = p->rchild;
}
}
}
//递归求二叉树高度
int countLevelOfBiTree1(BiTree p){
if (p == NULL){
return 0;
}
int lel = countLevelOfBiTree1(p->lchild);
int ler = countLevelOfBiTree1(p->rchild);
return lel > ler ? lel +1: ler+1;
}
//非递归求二叉树的高度,在非递归层次遍历基础上修改
/************************************************************************/
/* 因为访问完一层之后,这一层所有结点的子节点也已经完全进入队列。
* 根据这个特点来计算二叉树层次
* 我们使用visitedNumber表示出栈的元素的下标,enQueNumber表示进栈元素的下标,lastNumberOfOneLevel表示一层当中最后一个元素的下标
* 每次访问结点时:visitedNumber+1,进栈时:enQueNumber+1,当一层所有的元素都出栈时lastNumberOfOneLevel=下一层最后一个元素的下标。
*
*/
/************************************************************************/
int countLevelOfBiTree2(BiTree p){
BiTNode *queue[MAX_SIZE];
int front= 0, rear = 0;
queue[rear++] = p;
int visitedNumber = 0;
int enQueNumber = 1; //当前入栈的序号,root为1
int lastNumberOfOneLevel = 1; //因为已经有一个入队列
int height = 0;
while(front != rear){
p = queue[front++];
visitedNumber++;
if ( p->lchild != NULL){
queue[rear++] = p->lchild;
enQueNumber++;
}
if ( p->rchild != NULL){
queue[rear++] = p->rchild;
enQueNumber++;
}
if (lastNumberOfOneLevel == visitedNumber){
height ++;
lastNumberOfOneLevel = enQueNumber;
}
}
return height;
}
//求一点在树的那层。非递归形式,
int getLevelOfOneNodeInBiTree(BiTree p,char item){
BiTNode *queue[MAX_SIZE];
int front= 0, rear = 0;
queue[rear++] = p;
int visitedNumber = 0;
int enQueNumber = 1; //当前入栈的序号,root为1
int lastNumberOfOneLevel = 1; //因为已经有一个入队列
int height = 0;
while(front != rear){
p = queue[front++];
visitedNumber++;
if ( p->lchild != NULL){
queue[rear++] = p->lchild;
enQueNumber++;
}
if ( p->rchild != NULL){
queue[rear++] = p->rchild;
enQueNumber++;
}
if (lastNumberOfOneLevel == visitedNumber){
height ++;
lastNumberOfOneLevel = enQueNumber;
}
if (item == p->data){
if (lastNumberOfOneLevel < enQueNumber){
return height + 1;
} else {
return height;
}
}
}
return -1;
}
//求一点在树的那层。递归形式
void getLevelOfOneNodeInBiTree2(BiTree p,char item,int i,int *n){
if (p == NULL){
return;
}
if (item == p->data){
*n = i;
} else {
getLevelOfOneNodeInBiTree2(p->lchild,item,i+1,n);
getLevelOfOneNodeInBiTree2(p->rchild,item,i+1,n);
}
}
//递归判断两棵二叉树是否相似
int similarBiTree(BiTree p1,BiTree p2){
if (p1 == NULL && p2 == NULL){
return 1;
} else if (p1 == NULL || p2 == NULL){
return 0;
} else {
return(similarBiTree(p1->rchild,p2->rchild)*similarBiTree(p1->lchild,p2->lchild));
}
}
/************************************************************************/
/*判断一棵二叉树是不是完全二叉树。
*分为两种情况:
*一、二叉树采用顺序存储方式,这种方式中,只从前向后判断没有空节点即可。
*
*二、树采用链表形式进行存储,这个时候,只要对二叉树按层进行遍历判断:
*
*1、某结点没有左孩子,则一定没有右孩子。
*2、某结点如果没有左孩子或右孩子,那么其后序结点一定没有孩子。
*/
/************************************************************************/
int fullBiTree(BiTree p){
BiTNode *queue[MAX_SIZE];
int front= 0, rear = 0;
queue[rear++] = p;
int haveChild = 1;
while(front != rear){
p = queue[front++];
if (p->lchild == NULL && p->rchild != NULL){
return 0;
}
if (!haveChild && (p->lchild != NULL || p->rchild != NULL)){
return 0;
}
if (p->lchild == NULL || p->rchild == NULL ){
haveChild = 0;
}
if ( p->lchild != NULL){
queue[rear++] = p->lchild;
}
if ( p->rchild != NULL){
queue[rear++] = p->rchild;
}
}
return 1;
}
//输出根节点到P结点的路径
//采用非递归后序形式判断,当输出元素与结点元相同时,栈中的所有元素就是路径。
void printPath(BiTree p , char s){
BiTNode *stack[MAX_SIZE];
int top = -1;
stack[++top] = p;
p = p->lchild;
BiTNode * pre=NULL;
while (top >-1){
while (p != NULL){
stack[++top] = p;
p = p->lchild;
}
pre = NULL;
while (top>-1){
p = stack[top];
if (p ->rchild == pre){
//找到这个结点了,将这时栈中的所有元素输出。
if(p->data == s){
while(top>-1){
printNodeData(stack[top--]);
}
break;
}
top--;
pre = p;
} else {
p= p->rchild;
break;
}
}
}
}
//得到两个结点的最近的共同祖先
/************************************************************************/
/*
采用非递归后序形式判断,当输出元素与结点元相同时,栈中的所有元素就是该元素的路径。
设置一个对每个结点设置一个标志位,标识是否是一个元素的祖先结点,当是祖先结点时,
将该标志位设置为1,当第二个元素再次访问该标志位时如果是0,则将其设置为1,如果为1
表示,当前结点是另外一个节点的祖先结点,因此将其输出即可。
注意:遍历栈中的元素时采用从栈顶到栈尾的方式遍历。
*/
/************************************************************************/
char getAncestorOfTwoNode(BiTree p,char p1,char p2){
BiTNodeTag stack[MAX_SIZE];
int top = -1;
top++;
stack[top].btnode = p;
stack[top].tag = 0;
p = p->lchild;
BiTNode * pre = NULL;
int i = 0;
while(top > -1){
while(p != NULL){
top++;
stack[top].btnode = p;
stack[top].tag = 0;
p = p->lchild;
}
pre = NULL;
while(top > -1){
p = stack[top].btnode;
//判断是否是第二次入栈
if (pre == p ->rchild){
//printNodeData(p);
if (p->data == p1 || p->data == p2){
for (i = top;i >= 0;i--){
if (stack[i].tag == 0){
stack[i].tag = 1;
} else {
return (stack[i].btnode)->data;
}
}
}
top--;
pre = p;
} else {
p = p->rchild;
break;
}
}
}
return '-';
}
//拆分二叉树,输入一个节点值,将以这个值为根节点的树分为两个树。
BiTNode* disLink(BiTNode **p,char data){
BiTNode *stack[MAX_SIZE];
int top = -1;
BiTNode *t = NULL;
while (top > -1 || *p != NULL){
if (p != NULL){
//printNodeData(*p);
if (data == (*p)->data){
t = *p;
p = NULL;
break;
}
stack[++top] = *p;
*p = (*p)->lchild;
} else {
*p = stack[top--];
*p = (*p)->rchild;
}
}
return t;
}
//统计二叉树的结点个数。遍历二叉树即可
int countNodes(BiTree p){
BiTNode *stack[MAX_SIZE];
int top = -1;
int count = 0;
while(p != NULL || top>-1){
while(p != NULL){
stack[++top] = p;
p = p->lchild;
}
if (top>-1){
p = stack[top--];
// printNodeData(p);
count++;
p=p->rchild;
}
}
return count;
}
/*******************************线索二叉树相关操作开始********************************************/
//创建中序的线索二叉树,对其进行线索化。
BiThrNode * inOrderTreading(BiThrNode *p){
BiThrNode* stack[MAX_SIZE];
int top = -1;
BiThrNode* pre = NULL;
BiThrNode *root = p;
while(top > -1 || p != NULL){
while (p != NULL){
stack[++top] = p;
p = p ->lchild;
}
if (top > -1){
p = stack[top--];
//证明这是第一个结点
if (pre == NULL){
p->lchild = NULL;
}else{
//建立后记线索
if (pre ->rchild == NULL){
pre ->rtag = 1;
pre->rchild = p;
}
//建立前驱线索
if (p->lchild == NULL){
p ->lchild = pre;
p->ltag = 1;
}
}
//设置前前一个结点。
pre = p;
//printf("%c",p->data);
p = p->rchild;
} else {
break;
}
}
return root;
}
//申请一个线索二叉树结点
BiThrNode * mallocBiThrNode(char s){
BiThrNode *root = (BiThrNode *)malloc(sizeof(BiThrNode));
root->data = s;
root->lchild = NULL;
root->rchild = NULL;
root->ltag = 0;
root->rtag = 0;
return root;
}
//构建线索二叉树
BiThrNode * createThrTree(){
char str[] ="ABC@G@@@DE@@@";
char *ps = str;
BiThrNode *stack[MAX_SIZE];
int top = -1;
if (*ps == '@'){
printf("空线索二叉树");
exit(0);
}
BiThrNode *root = mallocBiThrNode(*ps);
ps++;
stack[++top] = root;
BiThrNode *p = root;
BiThrNode *temp ;
int rl = 1;
while(*ps != '\0'){
if (*ps != '@'){
if (rl == 1){
temp = mallocBiThrNode(*ps);
p->lchild = temp;
p = temp;
stack[++top] = p;
} else {
temp = mallocBiThrNode(*ps);
p->rchild = temp;
p = temp;
stack[++top] = p;
rl = 1;
}
} else {
if (rl == 1){
rl = 2;
}
if (top > -1){
p = stack[top--];
} else {
break;
}
}
ps++;
}
return root;
}
//找到某个结点的后继结点
BiThrNode * succ(BiThrNode * p){
if (p->rtag == 1){
return p->rchild;
} else {
//中序遍历特点LDR,后继结点当前结点处于D处,因为已经访问到当前结点了。
//所以需要从右子树找后继结点,从LDR的特点来看,这个结点就是右子树的最左侧的那个节点。
//为什么要使用ltag呢,因为,所有的lchild属性都已经使用了。
if ((p = p->rchild)!= NULL){
while(p->ltag == 0){
p = p->lchild;
}
}
return p;
}
}
//找到某个树的前驱结点
BiThrNode * pre(BiThrNode *p){
if (p->ltag == 1){
return p->lchild;
} else {
//中序遍历特点LDR,后继结点当前结点处于D处,因为已经访问到当前结点了。
//所以需要从左子树找前驱结点,从LDR的特点来看,这个结点就是左子树的最右侧的那个节点。
//p = p->lchild;
if ((p = p->lchild) != NULL){
while(p->rtag == 0){
p = p->rchild;
}
}
return p;
}
}
//非递归输出中序遍历线索二叉树
void inOrderTraverseThrTree(BiThrNode * p){
BiThrNode * temp;
//LDR中序遍历,先找前序结点
while(p != NULL){
temp = p;
p = pre(p);
}
p = temp;
while(p != NULL){
printf("%c",p->data);
p = succ(p);
}
}
/*******************************线索二叉树相关操作结束********************************************/
typedef struct BiTreeNode{
//保存原始值
char s;
//是否访问过
int flag;
//
BiTNode *p;
}BiTreeNode;
int getPositionOfNode(char s, BiTreeNode *nodes,int len);
int getPostionBetweenPos1AndPos2(int pos1, int pos2,BiTreeNode *nodes);
//由前序和中序序列得到二叉树,非递归
//实际上,只要将后序序列,前后调换顺序,得到的二叉树是一样的。因此,后序就不再写了。
BiTNode * getBiTreeByPreAndIn(char * p1,char *p2){
int len = strlen(p2);
BiTreeNode *nodes = new BiTreeNode[len];
int i = 0;
//初始化
for (i = 0;i < len ;i++){
nodes[i].s = *(p2+i);
nodes[i].flag = 0;
nodes[i].p = (BiTNode *)malloc(sizeof(BiTNode));
nodes[i].p->data = *(p2+i);
nodes[i].p->lchild = NULL;
nodes[i].p->rchild = NULL;
}
BiTNode *root = NULL;
//后序和中序时,读出后序的最后一个在中序中找到并标识
for (i = 0;i<len;i++){
//将根节点设置为已读
if (nodes[i].p->data == *p1){
nodes[i].flag = 1;
root = nodes[i].p;
}
}
//后序时,只要将其i从大往小递减即可
for (i = 0;i<len-1;i++){
int pos1 = getPositionOfNode(p1[i],nodes,len);
int pos2 = getPositionOfNode(p1[i+1],nodes,len);
int pos3 = getPostionBetweenPos1AndPos2(pos1,pos2,nodes);
//设置为已读
nodes[pos2].flag = 1;
if (pos3 > pos2){
nodes[pos3].p->lchild = nodes[pos2].p;
} else {
nodes[pos3].p->rchild = nodes[pos2].p;
}
}
return root;
}
int getPositionOfNode(char s, BiTreeNode *nodes,int len){
int i = 0;
for (i = 0;i<len;i++){
if (s == nodes[i].s){
return i;
}
}
}
int getPostionBetweenPos1AndPos2(int pos1, int pos2,BiTreeNode *nodes){
int i = 0;
//得到pos1和pos2之间离pos2最近的已经访问过的那个结点的位置。
if (pos1 > pos2){
for (i=pos2;i<=pos1;i++){
if (nodes[i].flag ==1){
return i;
}
}
} else {
for (i = pos2;i>=pos1;i--){
if (nodes[i].flag ==1){
return i;
}
}
}
}
//由前序和中序序列得到二叉树,递归
BiTNode * getBiTreeByPreAndIn2(char * ppos,char *ipos,int n){
BiTNode *ptr;
char *rpos;
int k;
if (n <= 0){
return NULL;
}
ptr = (BiTNode*)malloc(sizeof(BiTNode));
ptr->data = *ppos;
for (rpos = ipos;rpos <ipos+n;rpos++){
if (*rpos == *ppos){
break;
}
}
//根结点的位置
k = rpos -ipos;
ptr->lchild = getBiTreeByPreAndIn2(ppos+1,ipos,k);
ptr->rchild = getBiTreeByPreAndIn2(ppos+1+k,rpos+1,n-1-k);
return ptr;
}
void main(){
BiTNode * root = createBiTree();
printf("前序遍历:\n");
preOrderTraverse(root);
printf("\n");
preOrderTraverse1(root);
printf("\n");
preOrderTraverse2(root);
printf("\n");
preOrderTraverse3(root);
printf("\n\n");
printf("中序遍历:\n");
inOrderTraverse(root);
printf("\n");
inOrderTraverse1(root);
printf("\n\n");
printf("后序遍历:\n");
postOrderTraverse(root);
printf("\n");
postOrderTraverse1(root);
printf("\n");
postOrderTraverse2(root);
printf("\n");
postOrderTraverse3(root);
printf("\n");
postOrderTraverse4(root);
printf("\n\n");
printf("层次遍历:\n");
levelOrderTraverse(root);
printf("\n");
levelOrderTraverse1(root);
printf("\n");
levelOrderTraverse2(root);
printf("\n\n");
printf("二叉树的高度:\n");
printf("the level is %d\n",countLevelOfBiTree1(root));
printf("the level is %d\n",countLevelOfBiTree2(root));
printf("\n");
printf("查找某点在二叉树的那一层:\n");
printf("the level of %c in BiTree is %d\n",'E',getLevelOfOneNodeInBiTree(root,'E'));
int i = 0;
getLevelOfOneNodeInBiTree2(root,'E',1,&i);
printf("the level of %c in BiTree is %d",'E',i);
printf("\n\n");
printf("判断两棵二叉树是否相似:\n");
printf("%d",similarBiTree(createBiTree(),createBiTree()));
printf("\n\n");
printf("判断二叉树是不是完全二叉树:\n");
printf("the tree is full tree %d",fullBiTree(root));
printf("\n\n");
printf("输出某一结点的到跟结点的路径:\n");
printf("The path of the itme is ");
printPath(root,'D');
printf("\n\n");
printf("得到两个结点的最近的共同祖先: \n");
printf("The common item is %c",getAncestorOfTwoNode(root,'C','G'));
printf("\n\n");
//printf("拆分二叉树: \n");
//preOrderTraverse(disLink(&root,'B'));
//printf("\n");
指针没掌握好,没调试出来。
//preOrderTraverse(root);
//printf("\n\n");
printf("统计二叉树的结点个数:\n");
printf("The count of the BinTree is %d",countNodes(root));
printf("\n\n");
printf("线索中序二叉树的建立和输出:\n");
BiThrNode *thRoot = inOrderTreading(createThrTree());
inOrderTraverseThrTree(thRoot);
printf("\n\n");
printf("根据前序和中序建立二叉树:\n");
postOrderTraverse4(getBiTreeByPreAndIn("abdgcefhi","dgbaechif"));
printf("\n");
postOrderTraverse4(getBiTreeByPreAndIn2("abdgcefhi","dgbaechif",9));
printf("\n");
}