关于二叉树的相关操作汇总

关于二叉树的相关操作汇总,其中包含以下操作:

  1. 递归前序遍历
  2. 非递归前序遍历
  3. 递归中序遍历
  4. 非递归中序遍历
  5. 递归后序遍历
  6. 非递归后序遍历
  7. 递归层次遍历
  8. 非递归层次遍历
  9. 递归计算二叉树的高度
  10. 非递归计算二叉树高度
  11. 递归查找某点在二叉树的那一层
  12. 非递归查找某点在二叉树的那一层
  13. 判断两棵二叉树是否相似
  14. 判断二叉树是不是完全二叉树
  15. 输出某一结点的到跟结点的路径
  16. 得到两个结点的最近的共同祖先
  17. 拆分二叉树
  18. 统计二叉树的结点个数
  19. 线索中序二叉树的建立
  20. 线索中序二叉树的输出
  21. 根据前序和中序非递归建立二叉树
  22. 根据前序和中序递归建立二叉树

#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");
}


  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值