【数据结构】“树”的常用代码总结(C语言)

“树”的常用代码总结(数据结构)

首先本文采用的主要是采用二叉树的二叉链表存储

二叉树的二叉链表存储表示

BiTNode 其实就是 Binary(二)Tree(树) Node(结点)
包括 数据域左右孩子结点的指针域

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

树的二叉链表(孩子 - 兄弟)存储表示

typedef struct CSNode
{
	int data;
	struct CSNode *firstchild, *nextsibling;
}CSNode, *CSTree;

创建二叉树(先序输入&递归建立)

按先序遍历顺序输入二叉树的各个结点值,#表示空节点,建立二叉树。

void CreatBiTree(BiTree &T)
{
	char ch;
	scanf("%c",&ch);
	if(ch == '#')
	{
        T = NULL;
	}
	else
	{
        T = (BiTree)malloc(sizeof(BiTNode));
        T->data = ch;
        CreatBiTree(T->lchild);
        CreatBiTree(T->rchild);
	}
}

二叉树遍历(递归)

这里展示的是二叉树的中序遍历和先序遍历,只要稍微变一下printf(“%c”,T->data);的位置。printf(“%c”,T->data);相当于遍历时每个双亲。它在什么位置,就是什么遍历。

二叉树先序遍历(递归)
void  PreOrderTraverse(BiTree T)
{
	if(T)
	{
        printf("%c",T->data);  //先序遍历此条语句在前面
        PreOrderTraverse(T->lchild);
        PreOrderTraverse(T->rchild);
	}
}
二叉树中序遍历(递归)
void  InOrderTraverse(BiTree T)
{
	if(T)
	{
        InOrderTraverse(T->lchild);
        printf("%c",T->data);  //中序遍历此条语句在中间
        InOrderTraverse(T->rchild);
	}
}
二叉树后序遍历(递归)
//后序遍历二叉树
void PostOrderBiTree(BiTree T)
{
    if (T)
    {
        PostOrderBiTree(T->lChild);
        PostOrderBiTree(T->rChlid);
        printf("%d ", T->data);  //后序遍历此条语句在最后
    }
}

求二叉树的深度(高度)

int TreeDeep(BiTree T)
{
    int deep = 0;
    if(T)
    {
        int leftdeep = TreeDeep(T->lchild);
        int rightdeep = TreeDeep(T->rchild);
        deep = leftdeep>=rightdeep?leftdeep+1:rightdeep+1;
    }
    return deep;
}

由二元组建立孩子兄弟二叉树

以双亲孩子二元组(F,C)的形式自上而下、自左而右依次输入树的各边,建立树的孩子-兄弟链表

void CreateCSTree(CSTree &T) 
{
    int input[2],n,i;
    CSTree queue[MAXSIZE];
    int front,rear;
    CSTree p, q;

    scanf("%d",&n);

    //对队列初始化
    front = rear = 0;

    for (i=0; i<n; i++) 
    {
        scanf("%d",&input[0]);
        scanf("%d",&input[1]);
        //创建当前孩子结点
        p = (CSTree)malloc(sizeof(CSNode)); 
        p->data = input[1];
        //孩子结点和兄弟结点赋值为空 
        p->firstchild = p->nextsibling = NULL;

        //将刚刚创建好的当前孩子结点放入队尾 
        queue[rear] = p;
        rear = (rear+1)%MAXSIZE;

        /*********找双亲*********/

        //如果是根结点,则不需找双亲
        if (input[0] == -1) 
        {
            T = p; //将刚刚创建的结点赋值为根结点 
        }

        //如果不是根结点,则找双亲 
        else
        {
            //从头到尾遍历当前所有兄弟找双亲,得到双亲的指针 
            for (q=queue[front]; q->data!=input[0];)
        {
             //如果队头元素和当前双亲结点不同,则出队
            //最终获得的指针即其双亲的指针 
            front=(front+1)%MAXSIZE;
            q=queue[front]; 
        }
        /*找到双亲后找哥哥*/ 
        //如果找到的双亲还不存在孩子结点 
        if (!q->firstchild) 
        {
            q->firstchild=p; 
        }
        //如果已有孩子结点。则要找到最近的哥哥
        else
        {
            for(q=q->firstchild; q->nextsibling; q=q->nextsibling);
            q->nextsibling = p;//和哥哥连接 
        }
    }
}
return 0;
}

求孩子兄弟链表表示的树 T的深度

int depthCSTree(CSTree T)
{ 
	int maxd, d;	
    CSTree p;	
	if(!T) return 0; //空树	
	else 
	{		
        for(maxd=0,p=T->firstchild; p; p=p->nextsibling)
        if((d=depthCSTree(p)) > maxd) maxd = d; //子树的最大深度
        return maxd + 1;  
	}
}

输出孩子兄弟链表表示的树 T所有叶子结点值

void  InOrderTraverse_leaf(CSTree T)
{
	if(T)
	{
        if(!T->firstchild)
        {
            printf("%d ",T->data);
        }
        InOrderTraverse_leaf(T->firstchild);
        InOrderTraverse_leaf(T->nextsibling);
	}
}

二元组建树并求其叶子结点和深度

此代码用到的所有函数在上面已经全部展示过了
其中 system(“color F0\n”); 语句可以将控制台变为白底黑字

int main()
{
	system("color F0\n"); 
    CSTree T;
	int deep;
	CreateCSTree(T);
	InOrderTraverse_leaf(T);
	printf("\n");
    deep = depthCSTree(T);
	printf("%d\n",deep);
}

求每个结点的深度

此时在二叉树的存储结构中添加一个深度元素,像这样:
typedef struct BiTNode
{
 char data;
 int deep;
 struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;

void node_deep(BiTree &T)
{
	if(T)
	{
        if(T->lchild)
            T->lchild->deep = T->deep + 1;
        if(T->rchild)
            T->rchild->deep = T->deep + 1;
        node_deep(T->lchild);
        node_deep(T->rchild);
	}
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值