目录
一、树的双亲表示
存储结构
采用结构体数组的形式存储数据。
(根结点parent=1:它没有双亲结点了)
//树的双亲表示
typedef struct
{
char data; //结点数据
int parent; //双亲在数组中的位置
}Tree;
Tree tree[MAXSIZE];
总代码
//树的双亲表示法(双亲树)
//getchar():吸收换行符
#include<stdio.h>
#define MAXSIZE 20
int count = 0;
//树的双亲表示
typedef struct
{
char data; //结点数据
int parent; //双亲在数组中的位置
}Tree;
Tree tree[MAXSIZE];
//双亲树的初始化
void Init_Tree()
{
tree[0].parent = -1;
}
//创建树
void Create_Tree()
{
int i, n = 0;
printf("请输入结点个数:\n");
scanf_s("%d", &n);
getchar(); //这里吸收换行符
printf("请依次输入结点数据和双亲结点序号:\n");
for (i = 0; i < n; i++)
{
scanf_s("%c", &(tree[i].data)); //输入数据
scanf_s("%d", &(tree[i].parent)); //输入双亲结点
getchar(); //这里吸收换行符
count++;
}
}
//遍历树
void Traverse()
{
int i = 0;
for (i = 0; i < count; i++)
{
printf("%c的双亲结点:%d\n", tree[i].data, tree[i].parent);
}
}
int main()
{
Init_Tree(); //初始化
Create_Tree(); //创建树
Traverse(); //遍历树
return 0;
}
二、树的孩子表示
存储结构
先创建一个结构体数组,用*firstchild连接它们的第一个孩子结点,用*next连接后面的孩子结点。最后把地址赋空(注:这里把地址赋空用的是二级指针,能同步改变根结点的地址,但凡需要地址的改变都要二级指针,二级指针是个难点,单独放在另一篇博客中)
//孩子结点
typedef struct Child
{
int child;
struct Child** next;
}Child, *pChild;
总代码
//树的孩子表示法
//两个结构体:
//一个结构体数组存放整体数据元素,里面有*firstchild指针指向第一个孩子
//一个孩子链表存放孩子信息
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <malloc.h>
#define MAXSIZE 20
int length = 0; //数组长度
//孩子结点
typedef struct Child
{
int child;
struct Child** next;
}Child, * pChild; //*pChild:创建二级指针
//树
typedef struct
{
char data;
Child* firstchild;
}Tree;
Tree T[MAXSIZE];
//输入
void InputTree()
{
int i;
char ch;
Child* child;
printf("请输入您需要创建的结点数据:\n");
scanf("%c", &ch);
for (i = 0; i < MAXSIZE && ch != '\n'; i++)
{
T[i].data = ch;
scanf("%c", &ch);
}
length = i; //记录数据长度(数组)
}
//初始化
void InitTree()
{
int i;
for (i = 0; i < length; i++)
{
T[i].firstchild = NULL;
}
}
//根据结点数据查找孩子下标
int FindIndex(char ch)
{
int i = 0;
for (i = 0; i < length; i++)
{
if (T[i].data == ch)
return i;
}
return -1;
}
//创建树
void CreateTree()
{
int i = 0;
char ch;
pChild* p = NULL; //二级指针
for (i = 0; i < length; i++)
{
printf("请输入%c的孩子结点数据(没有就直接回车): ", T[i].data);
scanf("%c", &ch);
//首孩子
if (ch != '\n')
{
T[i].firstchild = (Child*)malloc(sizeof(Child)); //创建指向首孩子的指针
p = (pChild*)malloc(sizeof(pChild)); //孩子指针
p = &T[i].firstchild; //孩子指针指向首孩子指针
(*p)->child = FindIndex(ch);
(*p)->next = (pChild*)malloc(sizeof(pChild));
*((*p)->next) = NULL; //一级指针赋NULL
scanf("%c", &ch);
}
//后面的孩子
while (ch != '\n')
{
//二级指针的操作(给*p地址)
(*p)->next = (pChild*)malloc(sizeof(pChild)); //创建指向首孩子的指针 (p: 二级指针有地址)
p = (*p)->next; //后移 (next: 二级指针有地址)
//一级指针的操作(给*p地址)
(*p) = (Child*)malloc(sizeof(pChild)); //创建一级指针
(*p)->child = FindIndex(ch); //(*p)一级指针并没有地址!!!
//在二级指针的基础上,要把一级指针浮NULL,必须得先给二级指针地址
(*p)->next = (pChild*)malloc(sizeof(pChild));
*((*p)->next) = NULL; //一级指针赋NULL
scanf("%c", &ch);
}
}
}
//遍历树
void Traverse()
{
int i;
Child* p = NULL;
for (i = 0; i < length; i++)
{
p = T[i].firstchild;
printf("\n%c的孩子结点(下标):", T[i].data);
while (p != NULL)
{
printf("%d ", p->child);
p = *(p->next);
}
}
}
int main()
{
InputTree();
InitTree();
CreateTree(); //创建树
Traverse(); //遍历
return 0;
}
三、树的双亲孩子表示
存储结构
总代码
//树的双亲孩子表示法
#include <stdio.h>
#include <malloc.h>
#define MAXSIZE 20
int sum = 0;
//孩子结点
typedef struct Child
{
int index;
struct Child* next;
}Child;
Child* now;
//树
typedef struct
{
char data;
int childNum;
char parent;
Child* firstchild;
}Tree;
Tree tree[MAXSIZE];
//初始化
void Init_Tree()
{
now = (Child*)malloc(sizeof(Child));
tree[0].parent = NULL;
}
//创建树
void Create_Tree()
{
int num, i, j;
Child* child;
printf("请输入您需要创建的结点个数:\n");
scanf_s("%d", &sum); //结点总数
getchar();
//输入数组列表
for (i = 0; i < sum; i++)
{
printf("\n请输入第%d个结点数据:\n", i + 1);
scanf_s("%c", &tree[i].data); //输入数据
getchar();
printf("请输入%c结点的孩子结点个数:\n", tree[i].data);
scanf_s("%d", &num); //孩子节点总数
getchar();
//输入孩子结点
if (num) //num!=0
printf("请分别输入%c结点的孩子结点在数组中的位置:\n", tree[i].data);
for (j = 0; j < num; j++)
{
child = (Child*)malloc(sizeof(Child)); //创建孩子结点
child->next = NULL;
scanf_s("%d", &child->index); //孩子节点在数组中的下标
getchar();
tree[child->index].parent = tree[i].data; //设置孩子结点的双亲结点
//连接到上一个
if (j == 0)
{
tree[i].firstchild = child;
child->next = NULL;
}
else
{
now->next = child; //指向当前结点
}
now = child;
tree[i].childNum++;
}
}
}
//遍历树
void Traverse()
{
int i, j;
Child* now;
for (i = 0; i < sum; i++)
{
printf("\n第%d个结点:%c\n", i + 1, tree[i].data);
now = tree[i].firstchild; //指向第一个叶子结点
printf("%c结点的双亲结点:%c\n", tree[i].data, tree[i].parent);
for (j = 0; j < tree[i].childNum; j++)
{
printf("%c结点的第%d个孩子结点:%c\n", tree[i].data, j + 1, tree[now->index].data);
now = now->next; //往后移
}
}
}
int main()
{
Init_Tree();
Create_Tree(); //创建树
Traverse(); //遍历
return 0;
}