/*
问题描述:
将树变成二叉树
引例:《数据结构(C语言版)》清华大学出版社
P135下图
input.data 数据如下:
10
R
A
R
B
R
C
R
D
A
E
A
F
C
G
F
H
F
K
F
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_TREE_SIZE 20
typedef char TElemType;
typedef struct CTNode{
int child;
struct CTNode * next;
}ChildPtr;
typedef struct{
int parent;//保存父亲结点下标
TElemType data;
ChildPtr * firstchild;
}CTBox;
typedef struct{
CTBox nodes[MAX_TREE_SIZE];
int n,r;
}CTree;
CTree * Init()
{
CTree *ct;
ChildPtr *p,*q;
int i,j;
char temp;
ct = (CTree *)malloc(sizeof(CTree));
memset(ct,0,sizeof(CTree));
printf("请输入树的结点个数:");
scanf("%d",&ct->n);
getchar();
//输入每个结点的信息
//输入顺序:按层,每层从左往右
for(i=0;i<ct->n;i++){
printf("请输入第%d个结点的信息:\n",i+1);
printf("请输入该结点的字母信息:\n");
scanf("%c",&ct->nodes[i].data);
getchar();
if(i){//不是根结点
printf("请输入该结点的父亲结点的字母信息:");
scanf("%c",&temp);
getchar();
for(j=0;j<i && ct->nodes[j].data - temp;j++);
if(j == i){
printf("查询父亲结点失败!\n");
exit(0);
}
ct->nodes[i].parent = j;//设置从当前结点到父亲结点的指向
//遍历当前结点的父亲结点的孩子链,给其添加当前结点的信息 (装箱算法)
p = (ChildPtr *)malloc(sizeof(ChildPtr));
p->child = i;
p->next = NULL;
for(q = ct->nodes[j].firstchild ;q && q->next; q = q->next);
if(q){//该结点不是第一个孩子
q->next = p;
}
else//该结点是第一个孩子
ct->nodes[j].firstchild = p;
}
else{//是根结点,自动确定父亲结点为-1
ct->nodes[i].parent = -1;
ct->r = i;
}
}
return ct;
}
void PrintCTree(CTree *ct)
{
int i;
ChildPtr *p;
for(i=0;i<ct->n;i++){
printf("下标:%d 父亲下标:%d 数据:%c 孩子下标:",i,ct->nodes[i].parent,ct->nodes[i].data);
for(p = ct->nodes[i].firstchild;p;p = p->next)
printf("%d ",p->child);
putchar('\n');
}
}
void TransForm(CTree *ct)
{
int i;
ChildPtr *left,*other,*p;
//把每个结点的孩子(如果有的话)分成最左边的孩子 和 其他的孩子两部分
//让其他的孩子的parent指向最左边的孩子
//即断掉除最左边孩子外其他孩子和父亲结点的关系
//删除父亲结点中除最左边孩子的信息外其他孩子的信息
//这些信息接在最左边孩子的原有的孩子信息的后面
for(i=0;i<ct->n;i++){
left = ct->nodes[i].firstchild;
if(left){//左孩子存在
if(ct->nodes[i].firstchild && ct->nodes[i].firstchild->next
&& !ct->nodes[i].firstchild->next->next && i != ct->r){
//孩子只有两个,无需转化
//根结点的孩子必须转化
continue;
}
for(other = left->next;other;other = other->next){
ct->nodes[other->child].parent = left->child;//改指向
}
other = left->next;
left->next = NULL;
for(p = ct->nodes[left->child].firstchild;p && p->next;p = p->next);
if(p){
p->next = other;
}
else
ct->nodes[left->child].firstchild = other;
}
}
}
void Preorder(CTree *ct,int subscript)
{
ChildPtr *p;
printf("%c ",ct->nodes[subscript].data);
p = ct->nodes[subscript].firstchild;
if(p){//如果有第一个孩子
Preorder(ct,p->child);
if(p->next)
Preorder(ct,p->next->child);
}
}
int main(void)
{
CTree *ct;
freopen("input.data","r",stdin);
//Init 文件input.data中测试用例 以书上所给图示为例
ct = Init();
printf("树信息如下:\n");
PrintCTree(ct);
printf("\n\n将树二叉树化:\n\n");
TransForm(ct);
PrintCTree(ct);
printf("\n\n二叉树中序遍历:\n\n");
Preorder(ct,ct->r);
return 0;
}
树变成二叉树
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.