数据结构个人笔记 第16课 二叉树的遍历

二叉树的遍历

二叉树先序遍历

二叉树先序遍历的实现思想是

  1. 访问根结点
  2. 访问当前节点的左子树
  3. 若当前节点无左子树,则访问当前节点的右子树

二叉树
由以上思想提出的遍历顺序为:

1,2,4,5,3,6,7

递归实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TElemType int

typedef struct BiTNode{
	TElemType data;
	struct BiTNode *lchild ,*rchild;
}BiTNode,*BiTree; 

void CreateBiTree(BiTree *T){
	*T = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->data = 1;
	(*T)->lchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T) -> rchild = (BiTNode*)malloc(sizeof(BiTNode));
	
	(*T)->lchild->data = 2;
	(*T)->lchild->lchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->lchild->rchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->lchild->rchild->data = 5;
	(*T)->lchild->rchild->lchild = NULL;
	(*T)->lchild->rchild->rchild = NULL;
	(*T)->rchild->data = 3;
	(*T)->rchild->lchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->rchild->lchild->data = 6;
	(*T)->rchild->lchild->lchild = NULL;
	(*T)->rchild->lchild->rchild = NULL;
	(*T)->rchild->rchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->rchild->rchild->data = 7;
	(*T)->rchild->rchild->lchild = NULL;
	(*T)->rchild->rchild->rchild = NULL;
	(*T)->lchild->lchild->data = 4;
	(*T)->lchild->lchild->lchild = NULL;
	(*T)->lchild->lchild->rchild = NULL;
}

void displayElem(BiTNode* elem){
	printf("%d ",elem->data);
}

void PreOrderTraverse(BiTree T){
	if(T){
		displayElem(T);
		PreOrderTraverse(T->lchild);
		PreOrderTraverse(T->rchild);
	}
	return;
}

int main(){
	BiTree Tree;
	CreateBiTree(&Tree);
	printf("先序遍历:\n");
	PreOrderTraverse(Tree);
}

运行结果:
在这里插入图片描述

非递归实现

而递归的底层实现依靠的是栈存储结构,因此,二叉树的先序遍历既可以直接采用递归思想实现,也可以使用栈的存储结构模拟递归的思想实现

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define TElemType int
int top = -1;//top变量时刻表示栈顶元素所在位置
typedef struct BiTNode{
	TElemType data;
	struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree; 

void CreateBiTree(BiTree *T){
	*T = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->data = 1;
	(*T)->lchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T) -> rchild = (BiTNode*)malloc(sizeof(BiTNode));
	
	(*T)->lchild->data = 2;
	(*T)->lchild->lchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->lchild->rchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->lchild->rchild->data = 5;
	(*T)->lchild->rchild->lchild = NULL;
	(*T)->lchild->rchild->rchild = NULL;
	(*T)->rchild->data = 3;
	(*T)->rchild->lchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->rchild->lchild->data = 6;
	(*T)->rchild->lchild->lchild = NULL;
	(*T)->rchild->lchild->rchild = NULL;
	(*T)->rchild->rchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->rchild->rchild->data = 7;
	(*T)->rchild->rchild->lchild = NULL;
	(*T)->rchild->rchild->rchild = NULL;
	(*T)->lchild->lchild->data = 4;
	(*T)->lchild->lchild->lchild = NULL;
	(*T)->lchild->lchild->rchild = NULL;
}

void push(BiTNode** a,BiTNode* elem){
	a[++top] = elem;
}

void pop(){
	if(top == -1){
		return;
	}
	top --;
}

void displayElem(BiTNode* elem){
	printf("%d ",elem->data);
}

BiTNode* getTop(BiTNode **a){
	return a[top];
}

void PreOrderTraverse(BiTree Tree){
	BiTNode* a[20];
	BiTNode *p;
	push(a,Tree);
	while(top != -1){
		p = getTop(a);
		pop();
		while(p){
			displayElem(p);
			if(p->rchild){
				push(a,p->rchild);
			}
			p = p->lchild; 
		}
	}
}

int main(){
	BiTree Tree;
	CreateBiTree(&Tree);
	printf("非递归先序遍历:\n");
	PreOrderTraverse(Tree);
}

结构如同上面递归实现

二叉树中序遍历

二叉树中序遍历的实现思想是

  1. 访问当前节点的左子树
  2. 访问根结点
  3. 访问当前节点的右子树

二叉树
这样得到的序列为:

4,2,5,1,6,3,7

递归实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TElemType int

typedef struct BiTNode{
	TElemType data;
	struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree; 

void CreateBiTree(BiTree *T){
	*T = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->data = 1;
	(*T)->lchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T) -> rchild = (BiTNode*)malloc(sizeof(BiTNode));
	
	(*T)->lchild->data = 2;
	(*T)->lchild->lchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->lchild->rchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->lchild->rchild->data = 5;
	(*T)->lchild->rchild->lchild = NULL;
	(*T)->lchild->rchild->rchild = NULL;
	(*T)->rchild->data = 3;
	(*T)->rchild->lchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->rchild->lchild->data = 6;
	(*T)->rchild->lchild->lchild = NULL;
	(*T)->rchild->lchild->rchild = NULL;
	(*T)->rchild->rchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->rchild->rchild->data = 7;
	(*T)->rchild->rchild->lchild = NULL;
	(*T)->rchild->rchild->rchild = NULL;
	(*T)->lchild->lchild->data = 4;
	(*T)->lchild->lchild->lchild = NULL;
	(*T)->lchild->lchild->rchild = NULL;
}

void displayElem(BiTNode * elem){
	printf("%d ",elem -> data);
}

void INOrderTraverse(BiTree T){
	if(T){
		INOrderTraverse(T->lchild);
		displayElem(T);
		INOrderTraverse(T->rchild);
	}
	return;
}

int main(){
	BiTree Tree;
	CreateBiTree(&Tree);
	printf("中序遍历算法:\n");
	INOrderTraverse(Tree);
}

结果展示
在这里插入图片描述

非递归实现

中序遍历的非递归方式实现思想是:从根结点开始,遍历左孩子同时压栈,当遍历结束,说明当前遍历的结点没有左孩子,从栈中取出来调用操作函数,然后访问该结点的左孩子,继续以上重复性的操作

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TElemType int
int top = -1;
typedef struct BiTNode{
	TElemType data;
	struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;

void CreateBiTree(BiTree *T){
	*T = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->data = 1;
	(*T)->lchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T) -> rchild = (BiTNode*)malloc(sizeof(BiTNode));
	
	(*T)->lchild->data = 2;
	(*T)->lchild->lchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->lchild->rchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->lchild->rchild->data = 5;
	(*T)->lchild->rchild->lchild = NULL;
	(*T)->lchild->rchild->rchild = NULL;
	(*T)->rchild->data = 3;
	(*T)->rchild->lchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->rchild->lchild->data = 6;
	(*T)->rchild->lchild->lchild = NULL;
	(*T)->rchild->lchild->rchild = NULL;
	(*T)->rchild->rchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->rchild->rchild->data = 7;
	(*T)->rchild->rchild->lchild = NULL;
	(*T)->rchild->rchild->rchild = NULL;
	(*T)->lchild->lchild->data = 4;
	(*T)->lchild->lchild->lchild = NULL;
	(*T)->lchild->lchild->rchild = NULL;
}

void push(BiTNode** a,BiTNode* elem){
	a[++top] = elem;
}

void pop(){
	if(top == -1){
		return;
	}
	top--;
}

void displayElem(BiTNode* elem){
	printf("%d ",elem->data);
}

BiTNode* getTop(BiTNode** a){
	return a[top];
} 

void InOrderTraverse1(BiTree Tree){
	BiTNode* a[20];
	BiTNode * p;
	push(a,Tree);
	while(top != -1){
		while((p = getTop(a)) && p){
			push(a,p->lchild); 
		}
		pop();
		if(top != -1){
			p = getTop(a);
			pop();
			displayElem(p);
			push(a,p->rchild);
		}
	}
}

void InOrderTraverse2(BiTree Tree){
	BiTNode* a[20];
	BiTNode * p;
	p = Tree;
	while(p || top != -1){
		if(p){
			push(a,p);
			p = p->lchild;
		}else{
			p = getTop(a);
			pop();
			displayElem(p);
			p = p->rchild;
		}
	}
}

int main(){
	BiTree Tree;
	CreateBiTree(&Tree);
	printf("中序遍历算法1:\n");
	InOrderTraverse1(Tree);
	printf("\n中序遍历算法2:\n");
	InOrderTraverse2(Tree);
}

二叉树后序遍历

二叉树后序遍历的实现思想是:从根结点触发,依次遍历各节点的左右子树,直到当前节点左右子树遍历完成后,才访问该节点元素

二叉树
遍历的结果:

4,5,2,6,7,3,1

递归实现

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define TElemType int 

typedef struct BiTNode{
	TElemType data;
	struct BiTNode *lchild, *rchild;
}BiTNode,*BiTree;

void CreateBiTree(BiTree *T){
	*T = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->data = 1;
	(*T)->lchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T) -> rchild = (BiTNode*)malloc(sizeof(BiTNode));
	
	(*T)->lchild->data = 2;
	(*T)->lchild->lchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->lchild->rchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->lchild->rchild->data = 5;
	(*T)->lchild->rchild->lchild = NULL;
	(*T)->lchild->rchild->rchild = NULL;
	(*T)->rchild->data = 3;
	(*T)->rchild->lchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->rchild->lchild->data = 6;
	(*T)->rchild->lchild->lchild = NULL;
	(*T)->rchild->lchild->rchild = NULL;
	(*T)->rchild->rchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->rchild->rchild->data = 7;
	(*T)->rchild->rchild->lchild = NULL;
	(*T)->rchild->rchild->rchild = NULL;
	(*T)->lchild->lchild->data = 4;
	(*T)->lchild->lchild->lchild = NULL;
	(*T)->lchild->lchild->rchild = NULL;
}

void displayElem(BiTNode* elem){
	printf("%d ",elem->data);
}

void PostOrderTraverse(BiTree T){
	if(T){
		PostOrderTraverse(T->lchild);
		PostOrderTraverse(T->rchild);
		displayElem(T);
	} 
	return;
}

int main(){
	BiTree Tree;
	CreateBiTree(&Tree);
	printf("后序遍历:\n");
	PostOrderTraverse(Tree);
}

结果展示:
在这里插入图片描述

非递归实现

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define TElemType int 
int top = -1;
typedef struct BiTNode{
	TElemType data;
	struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;

void CreateBiTree(BiTree *T){
	*T = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->data = 1;
	(*T)->lchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T) -> rchild = (BiTNode*)malloc(sizeof(BiTNode));
	
	(*T)->lchild->data = 2;
	(*T)->lchild->lchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->lchild->rchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->lchild->rchild->data = 5;
	(*T)->lchild->rchild->lchild = NULL;
	(*T)->lchild->rchild->rchild = NULL;
	(*T)->rchild->data = 3;
	(*T)->rchild->lchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->rchild->lchild->data = 6;
	(*T)->rchild->lchild->lchild = NULL;
	(*T)->rchild->lchild->rchild = NULL;
	(*T)->rchild->rchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->rchild->rchild->data = 7;
	(*T)->rchild->rchild->lchild = NULL;
	(*T)->rchild->rchild->rchild = NULL;
	(*T)->lchild->lchild->data = 4;
	(*T)->lchild->lchild->lchild = NULL;
	(*T)->lchild->lchild->rchild = NULL;
}

void pop(){
	if(top == -1){
		return;
	}
	top --;
}

void displayElem(BiTNode* elem){
	printf("%d ",elem->data);
}

typedef struct SNode{
	BiTree p;
	int tag;
}SNode;

void postpush(SNode *a,SNode sdata){
	a[++top] = sdata;
}

void PostOrderTraverse(BiTree Tree){
	SNode a[20];
	BiTNode * p;
	int tag;
	SNode sdata;
	p = Tree;
	while(p || top!=-1){
		while(p){
			sdata.p = p;
			sdata.tag = 0;
			postpush(a,sdata);
			p = p->lchild;
		}
		sdata = a[top];
		pop();
		p = sdata.p;
		tag = sdata.tag;
		if(tag == 0){
			sdata.p = p;
			sdata.tag = 1;
			postpush(a,sdata);
			p = p->rchild;
		}else{
			displayElem(p);
			p = NULL;
		}
		
	}
}

int main(){
	BiTree Tree;
	CreateBiTree(&Tree);
	printf("后序遍历:\n");
	PostOrderTraverse(Tree);
}

二叉树的层次遍历

按照二叉树中的层次从左到右依次遍历每层中的结点。具体的实现思路是:通过使用队列的数据结构,从树的根结点开始,依次将其左孩子和右孩子入队。而后每次队列中一个结点出列,都将其左孩子和右孩子入队,直到树中所有节点都出队,出队结点的先后顺序就是层次遍历的最终结果

在这里插入图片描述

运行结果:

1,2,3,4,5,6,7

实现代码

#include<stdio.h>
#include<stdlib.h>
#define TElemType int 

int front = 0,rear = 0; 

typedef struct BiTNode{
	TElemType data;
	struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;

void CreateBiTree(BiTree *T){
	*T = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->data = 1;
	(*T)->lchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T) -> rchild = (BiTNode*)malloc(sizeof(BiTNode));
	
	(*T)->lchild->data = 2;
	(*T)->lchild->lchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->lchild->rchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->lchild->rchild->data = 5;
	(*T)->lchild->rchild->lchild = NULL;
	(*T)->lchild->rchild->rchild = NULL;
	(*T)->rchild->data = 3;
	(*T)->rchild->lchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->rchild->lchild->data = 6;
	(*T)->rchild->lchild->lchild = NULL;
	(*T)->rchild->lchild->rchild = NULL;
	(*T)->rchild->rchild = (BiTNode*)malloc(sizeof(BiTNode));
	(*T)->rchild->rchild->data = 7;
	(*T)->rchild->rchild->lchild = NULL;
	(*T)->rchild->rchild->rchild = NULL;
	(*T)->lchild->lchild->data = 4;
	(*T)->lchild->lchild->lchild = NULL;
	(*T)->lchild->lchild->rchild = NULL;
}

void EnQueue(BiTree *a,BiTree node){
	a[rear++]=node;
}

BiTNode* DeQueue(BiTNode** a){
	return a[front++];
}

void displayNode(BiTree node){
	printf("%d ",node->data);
}

int main(){
	BiTree tree;
	CreateBiTree(&tree);
	BiTNode * p;
	BiTree a[20];
	EnQueue(a,tree);
	while(front < rear){
		p = DeQueue(a);
		displayNode(p);
		if(p->lchild != NULL){
			EnQueue(a,p->lchild);
		}
		if(p->rchild != NULL){
			EnQueue(a,p->rchild);
		}
	}
	return 0;
}

线索二叉树

在这里插入图片描述
上图所示的二叉链表,存在多个空指针域。空指针域的个数为n+1
可以在这n+1个空指针域中保存结点的前驱和后继指针,这样在下次遍历时,可以大大提高速度
在这里插入图片描述
将所有空指针域中的rchild指向它的后继
在这里插入图片描述
将所有空指针域中的lchild指向它的前驱

线索二叉树(保留遍历时结点在任一串行的前驱和后继的信息):若结点有左子树,则其lchild域指示其左孩子,否则令lchild域指示其前驱;若结点有右子树,则其rchild域指示其右孩子,否则令rchild指示其后继

还需在结点结构中增加两个标志域LTag和RTag。LTag=0时,lchild域指示结点的左孩子,LTag=1时,lchild域指示结点的前驱;RTag=0时,rchild域指示节点的右孩子,RTag=1时,rchild域指示结点的后继

以这种结点结构构成的二叉链表作为二叉树的存储结构,叫做线索链表,其中指向节点前驱和后继的指针叫做线索,加上线索的二叉树称为线索二叉树。对二叉树以某种次序遍历使其变为线索二叉树的过程称为线索化。若对二叉树进行中序遍历,则所得的线索二叉树称为中序线索二叉树,线索链表称为中序线索链表。

代码实现

#include <stdio.h>
#include <stdlib.h>
 
typedef int ElemType;
 
/*
线索存储标志位
Link(0):表示指向左右孩子的指针
Thread(1):表示指向前驱后继的线索
*/
typedef enum {Link, Thread} PointerTag;
 
typedef struct BiThrNode{
    ElemType data;
    struct BiThrNode *lchild, *rchild;
    PointerTag ltag;
    PointerTag rtag;
}BiThrNode, *BiThrTree;
 
//全局变量,始终指向刚刚访问过的节点
 BiThrTree pre;
 
//创建一棵二叉树,约定用户遵照前序遍历方式输入数据
void createBiThrTree(BiThrTree *T){
	*T = (BiThrNode*)malloc(sizeof(BiThrNode));
	(*T)->data = 1;
	(*T)->lchild = (BiThrNode*)malloc(sizeof(BiThrNode));
	(*T) -> rchild = (BiThrNode*)malloc(sizeof(BiThrNode));
	(*T)->ltag = Link;
	(*T)->rtag = Link;
	
	(*T)->lchild->data = 2;
	(*T)->lchild->lchild = (BiThrNode*)malloc(sizeof(BiThrNode));
	(*T)->lchild->rchild = (BiThrNode*)malloc(sizeof(BiThrNode));
	(*T)->lchild->rtag = Link;
	(*T)->lchild->ltag = Link;
	
	(*T)->lchild->rchild->data = 5;
	(*T)->lchild->rchild->lchild = NULL;
	(*T)->lchild->rchild->rchild = NULL;
	(*T)->lchild->rchild->ltag = Link;
	(*T)->lchild->rchild->rtag = Link;
	
	(*T)->rchild->data = 3;
	(*T)->rchild->lchild = (BiThrNode*)malloc(sizeof(BiThrNode));
	(*T)->rchild->ltag = Link;
	(*T)->rchild->rtag = Link;
	
	(*T)->rchild->lchild->data = 6;
	(*T)->rchild->lchild->lchild = NULL;
	(*T)->rchild->lchild->rchild = NULL;
	(*T)->rchild->lchild->ltag = Link;
	(*T)->rchild->lchild->rtag = Link;
	
	(*T)->rchild->rchild = (BiThrNode*)malloc(sizeof(BiThrNode));
	(*T)->rchild->rchild->data = 7;
	(*T)->rchild->rchild->lchild = NULL;
	(*T)->rchild->rchild->rchild = NULL;
	(*T)->rchild->rchild->ltag = Link;
	(*T)->rchild->rchild->rtag = Link;
	
	(*T)->lchild->lchild->data = 4;
	(*T)->lchild->lchild->lchild = NULL;
	(*T)->lchild->lchild->rchild = NULL;
	(*T)->lchild->lchild->ltag = Link;
	(*T)->lchild->lchild->rtag = Link;
}
 
//中序遍历线索化
void inThreading(BiThrTree T){
    if(T){
        inThreading(T->lchild);//递归左孩子线索华
        //节点处理
        if(!T->lchild){//处理前驱,什么时候能知道前驱,就是当前节点的时候,
//已经知道前一个是pre了,所以直接tag=thread,lchild=pre
            T->ltag = Thread;
            T->lchild = pre;
        }
        if(pre!=NULL && !pre->rchild){//处理后继,什么时候处理后继,只有访问到下一个的时候,
//才能知道下一个是谁,因为当访问下一个的时候,下一个是T,让pre的rchild指向T就好
            pre->rtag = Thread;
            pre->rchild = T;
        }
        pre = T;
 
        inThreading(T->rchild);//递归右孩子线索华
    }
}
 
//中序遍历线索二叉树---非递归
void InOrderThreading(BiThrTree T){
    BiThrTree p = T;
    while(p != NULL){
        //当ltag == Thread时,循环到中序序列第一个节点
        while(p->ltag == Link){
            p = p->lchild;
        }
 
        printf("%d ", p->data);
        while(p->rtag == Thread && p->rchild != NULL){
            p = p ->rchild;
            printf("%d ", p->data);
        }
        p = p->rchild;
    }
 
}
 
int main(){
    BiThrTree T = NULL;
    createBiThrTree(&T);
    inThreading(T);
    pre->rtag = Thread;
    InOrderThreading(T);
    return 0;
 
}

双向线索二叉树

双线线索链表的作用就是可以让线索二叉树从第一个节点和最后一个两个方向实现遍历

在线索二叉树的基础上,额外添加一个结点。此结点的作用类似于链表中的头指针,数据域不起作用,只利用两个指针域(由于都是指针,标志域都为0)

左指针域指向二叉树的树根,确保可以正方向对二叉树进行遍历;同时,右指针指向线索二叉树形成的线性序列中的最后一个节点
在这里插入图片描述

代码实现

#include <stdio.h>
#include <stdlib.h>
#define TElemType char//宏定义,结点中数据域的类型
//枚举,Link为0,Thread为1
typedef enum {
    Link,
    Thread
}PointerTag;
//结点结构构造
typedef struct BiThrNode{
    TElemType data;//数据域
    struct BiThrNode* lchild,*rchild;//左孩子,右孩子指针域
    PointerTag Ltag,Rtag;//标志域,枚举类型
}BiThrNode,*BiThrTree;

BiThrTree pre=NULL;

//采用前序初始化二叉树
//中序和后序只需改变赋值语句的位置即可
void CreateTree(BiThrTree * tree){
    char data;
    scanf("%c",&data);
    if (data!='#'){
        if (!((*tree)=(BiThrNode*)malloc(sizeof(BiThrNode)))){
            printf("申请结点空间失败");
            return;
        }else{
            (*tree)->data=data;//采用前序遍历方式初始化二叉树
            CreateTree(&((*tree)->lchild));//初始化左子树
            CreateTree(&((*tree)->rchild));//初始化右子树
        }
    }else{
        *tree=NULL;
    }
}
//中序对二叉树进行线索化
void InThreading(BiThrTree p){
    //如果当前结点存在
    if (p) {
        InThreading(p->lchild);//递归当前结点的左子树,进行线索化
        //如果当前结点没有左孩子,左标志位设为1,左指针域指向上一结点 pre
        if (!p->lchild) {
            p->Ltag=Thread;
            p->lchild=pre;
        }
        //如果 pre 没有右孩子,右标志位设为 1,右指针域指向当前结点。
        if (pre&&!pre->rchild) {
            pre->Rtag=Thread;
            pre->rchild=p;
        }
        pre=p;//pre指向当前结点
        InThreading(p->rchild);//递归右子树进行线索化
    }
}
//建立双向线索链表
void InOrderThread_Head(BiThrTree *h, BiThrTree t)
{
    //初始化头结点
    (*h) = (BiThrTree)malloc(sizeof(BiThrNode));
    if((*h) == NULL){
        printf("申请内存失败");
        return ;
    }
    (*h)->rchild = *h;
    (*h)->Rtag = Link;
    //如果树本身是空树
    if(!t){
        (*h)->lchild = *h;
        (*h)->Ltag = Link;
    }
    else{
        pre = *h;//pre指向头结点
        (*h)->lchild = t;//头结点左孩子设为树根结点
        (*h)->Ltag = Link;
        InThreading(t);//线索化二叉树,pre结点作为全局变量,线索化结束后,pre结点指向中序序列中最后一个结点
        pre->rchild = *h;
        pre->Rtag = Thread;
        (*h)->rchild = pre;
    }
}
//中序正向遍历双向线索二叉树
void InOrderThraverse_Thr(BiThrTree h)
{
    BiThrTree p;
    p = h->lchild;           //p指向根结点
    while(p != h)
    {
        while(p->Ltag == Link)   //当ltag = 0时循环到中序序列的第一个结点
        {
            p = p->lchild;
        }
        printf("%c ", p->data);  //显示结点数据,可以更改为其他对结点的操作
        while(p->Rtag == Thread && p->rchild != h)
        {
            p = p->rchild;
            printf("%c ", p->data);
        }
       
        p = p->rchild;           //p进入其右子树
    }
}
int main() {
    BiThrTree t;
    BiThrTree h;
    printf("输入前序二叉树:\n");
    CreateTree(&t);
    InOrderThread_Head(&h, t);
    printf("输出中序序列:\n");
    InOrderThraverse_Thr(h);
    return 0;
}

运行结果:
输入

124###35##6##

得到

4 2 1 5 3 6

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值