数据结构——树的相关算法实现


二叉树的基本算法

包括二叉树的遍历(先、中、后),二叉树的层次,二叉树的深度,二叉树的叶子节点数计算。相关算法思想可以看书,这里只是给出相关算法实现。

代码实现

#include 
#include 
#define MAXSIZE 30

typedef char ElemType;

typedef struct TNode {
	char data;
	TNode * lchild; 
	TNode * rchild;
}TNode, *BiTree;


int IsEmpty_BiTree(BiTree *T) {
	if(*T == NULL)
	return 1;//如果树为空一直进入死循环,直到输入数据为止 
	else
	return 0;
}

void Create_BiTree(BiTree *T){
    char ch;
    ch = getchar();
    //当输入的是"#"时,认为该子树为空
    if(ch == '#')
        *T = NULL;
    //创建树结点
    else{
        *T = (BiTree)malloc(sizeof(struct TNode));
        (*T)->data = ch; //生成树结点
        //生成左子树
        Create_BiTree(&(*T)->lchild);
        //生成右子树
        Create_BiTree(&(*T)->rchild);
    }
}

void TraverseBiTree(BiTree T) {	//先序遍历 
	if(T == NULL)//指针为空,说明节点不存在 
	return; 
	else {
		printf("%c ",T->data);
		TraverseBiTree(T->lchild);
		TraverseBiTree(T->rchild);
	}
	
}

void InOrderBiTree(BiTree T) {		//中序遍历 
	if(NULL == T)
	return;
	else {
		InOrderBiTree(T->lchild);
		printf("%c ",T->data);
		InOrderBiTree(T->rchild);	
	}
}

void PostOrderBiTree(BiTree T) {
	if(NULL == T)
	return;
	else {
		InOrderBiTree(T->lchild);
		InOrderBiTree(T->rchild);
		printf("%c ",T->data);
	}
	
} 

int TreeDeep(BiTree T) {
	int deep = 0;
	if(T)
	{
		int leftdeep = TreeDeep(T->lchild);
		int rightdeep = TreeDeep(T->rchild);
		deep = leftdeep+1 > rightdeep+1 ? leftdeep+1 : rightdeep+1; 
	}
	return deep;
}
//树的叶子结点为 
int Leafcount(BiTree T, int &num) {//一般涉及到变化的都会取地址 
	if(T)
	{
		if(T->lchild ==NULL && T->rchild==NULL)	
		{
			num++;
			printf("%c ",T->data);
		}			
		Leafcount(T->lchild,num);
		Leafcount(T->rchild,num);

	}
	return num;
}

//树的层次显示 (利用队列,先进先出的原则可以完美实现) 
void LevelOrder_BiTree(BiTree T){
    //用一个队列保存结点信息,这里的队列采用的是顺序队列中的数组实现
    int front = 0;
    int rear = 0;
    BiTree BiQueue[MAXSIZE];
    BiTree tempNode;
    if(!IsEmpty_BiTree(&T)){
        BiQueue[rear++] = T;
         
        while(front != rear){// 
            //取出队头元素,并使队头指针向后移动一位 
            tempNode = BiQueue[front++];
            //判断左右子树是否为空,若不为空,则加入队列 
            if(!IsEmpty_BiTree(&(tempNode->lchild)))
                BiQueue[rear++] = tempNode->lchild;
             
            if(!IsEmpty_BiTree(&(tempNode->rchild)))
                BiQueue[rear++] = tempNode->rchild;
             
             printf("%c ",tempNode->data);
        }
    }
}

int main(void)
{
	BiTree T;
	BiTree *p = (BiTree*)malloc(sizeof(BiTree));
	int deepth,num=0 ;
	Create_BiTree(&T);//一般涉及到变化的都会取地址 
	printf("先序遍历二叉树:\n");
	TraverseBiTree(T);
	printf("\n");
	printf("中序遍历二叉树:\n");
	InOrderBiTree(T);
	printf("\n");
	printf("后序遍历二叉树:\n");
	PostOrderBiTree(T);
	printf("\n层次遍历结果:");
    LevelOrder_BiTree(T);
	printf("\n");
	deepth=TreeDeep(T);
	printf("树的深度为:%d",deepth);
	printf("\n");
	printf("树的叶子结点为:");
	Leafcount(T,num);
	printf("\n树的叶子结点个数为:%d",num);
	return 0;
}

运行演示

线索二叉树的中序遍历

#include
#include 
using namespace std;

typedef struct BiThrNode
{
    char data;
	struct BiThrNode *lchild,*rchild;      /*左右孩子指针*/
	int LTag,RTag;             			    /*左右标志*/
}BiThrNode,*BiThrTree;

BiThrTree pre;



void CreateBiTree(BiThrTree *T){
    char ch;
    ch = getchar();
    //当输入的是"#"时,认为该子树为空
    if(ch == '#')
        *T = NULL;
    //创建树结点
    else{
        *T = (BiThrTree)malloc(sizeof(struct BiThrNode));
        (*T)->data = ch; //生成树结点
        //生成左子树
        CreateBiTree(&(*T)->lchild);
        //生成右子树
        CreateBiTree(&(*T)->rchild);
    }
}

/*以结点p为根的子树中序线索化*/
void InThreading(BiThrTree p)
{
	/*pre是全局变量,初始化时其右孩子指针为空,便于在树的最左点开始建线索*/
	if(p)
	{
		InThreading(p->lchild);            /*左子树递归线索化*/
		if(!(p->lchild) )                      /*p的左孩子为空*/
		{                  
			p->LTag=1;                     /*给p加上左线索*/
			p->lchild=pre;                 /*p的左孩子指针指向pre(前驱)*/
		}
		else
		{
			p->LTag=0;
		}
		if(!(pre->rchild) )                  /*pre的右孩子为空*/
		{
			pre->RTag=1;                  /*给pre加上右线索*/
			pre->rchild=p;                /*pre的右孩子指针指向p(后继)*/
		}
		else
		{
			pre->RTag=0;
		}
		pre=p;                            /*保持pre指向p的前驱*/
		InThreading(p->rchild);           /*右子树递归线索化*/
	}
}
/*带头结点的中序线索化*/
void InOrderThreading(BiThrTree &Thrt,BiThrTree T)
{
	/*中序遍历二叉树T,并将其中序线索化,Thrt指向头结点*/
	Thrt=new BiThrNode;  		/*建头结头*/
	Thrt->LTag=0;               /*头结点有左孩子,若树非空,则其左孩子为树根*/       
	Thrt->RTag=1;               /*头结点的右孩子指针为右线索*/
	Thrt->rchild=Thrt;          /*初始化时右指针指向自己*/
	if(!T) Thrt->lchild=Thrt;   /*若树为空,则左指针也指向自己*/
	else
	{
		Thrt->lchild=T; pre=Thrt; /*头结点的左孩子指向根,pre初值指向头结点*/
		InThreading(T);          /*调用上述算法,对以T为根的二叉树进行中序线索化*/
		pre->rchild=Thrt;        /*算法结束后,pre为最右结点,pre的右线索指向头结点*/
		pre->RTag=1;
		Thrt->rchild=pre;        /*头结点的右线索指向pre*/
	} 
}  
/*遍历中序线索二叉树*/
void InOrderTraverse_Thr(BiThrTree T)
{
	/*T指向头结点,头结点的左链lchild指向根结点*/
	/*中序遍历二叉线索树T的非递归算法,对每个数据元素直接输出*/
	BiThrTree p=T->lchild;    /*p指向根结点*/        
	while(p!=T)
	{
        while(p->LTag == 0)      /*沿左孩子向下*/
		{
		     p=p->lchild;
		}
		cout<data<<" ";           /*访问其左子树为空的结点*/
		while(p->RTag == 1 && p->rchild!=T)  /*沿右线索访问后继结点*/
		{
		    p=p->rchild;
			cout<data<<" ";
		}
		p=p->rchild;
	}
	cout<data;
}
int main()
{
	BiThrTree T;
	BiThrTree Thrt;
	cout<<"Input the Threaded BinaryTree 's node:"<

运行演示

二叉树结构图

参考文献

  • 数据结构-用C语言描述(第二版)[耿国华]