数据结构——树的相关算法实现
二叉树的基本算法
包括二叉树的遍历(先、中、后),二叉树的层次,二叉树的深度,二叉树的叶子节点数计算。相关算法思想可以看书,这里只是给出相关算法实现。
代码实现
#include <stdio.h>
#include <stdlib.h>
#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<iostream>
#include <stdlib.h>
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<<p->data<<" "; /*访问其左子树为空的结点*/
while(p->RTag == 1 && p->rchild!=T) /*沿右线索访问后继结点*/
{
p=p->rchild;
cout<<p->data<<" ";
}
p=p->rchild;
}
cout<<p->data;
}
int main()
{
BiThrTree T;
BiThrTree Thrt;
cout<<"Input the Threaded BinaryTree 's node:"<<endl;
CreateBiTree(&T);
InOrderThreading(Thrt,T); /*带头结点的中序线索化*/
cout<<"InOrderTraverse_Thr:"<<endl;
InOrderTraverse_Thr(T); /*遍历中序线索二叉树*/
return 0;
}
运行演示
二叉树结构图
参考文献
- 数据结构-用C语言描述(第二版)[耿国华]