“树”的常用代码总结(数据结构)
首先本文采用的主要是采用二叉树的二叉链表存储
二叉树的二叉链表存储表示
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);
}
}