树的存储结构
1.二叉树的存储
1.特殊二叉树的存储
对于完全二叉树的存储,只要根据完全二叉树编号的性质就可以通过数组进行存储
2.普通二叉树的存储(二叉树的链式存储)
首先可以采用补完全二叉树的办法,没有结点的地方补0,但这样有弊端,当一棵树的子结点只有左结点或只有右结点时,需要补充大量的0结点
2.树的存储结构
1.双亲表示法
具体代码
//树的双亲表示法结点结构定义
typedef int ElemType;
typedef struct PTNODE
{
Elemtype data;//结点数据
int parent;//双亲位置//双亲结点的下标
}PTNODE;
typedef struct
{
PTNODE node[MAX_SIZE];
int r;//根的位置
int n;//结点数目
}ptree;
//双亲表示法的完整代码
#include<stdio.h>
#include<stdlib.h>
#define MAX_SIZE 20
typedef char ElemType;//宏定义树结构中数据类型
typedef struct Snode //结点结构
{
ElemType data;
int parent;
}PNode;
typedef struct //树结构
{
PNode tnode[MAX_SIZE];
int n; //结点个数
}PTree;
PTree InitPNode(PTree tree)
{
int i,j;
char ch;
printf("请输出节点个数:\n");
scanf("%d",&(tree.n));
printf("请输入结点的值及双亲位于数组中的位置下标:\n");
for(i=0; i<tree.n; i++)
{
fflush(stdin);//清空缓冲区,不影响之后字符的读取
scanf("%c %d",&ch,&j);
tree.tnode[i].data = ch;
tree.tnode[i].parent = j;
}
return tree;
}
void FindParent(PTree tree)
{
char a;
int isfind = 0;
printf("请输入要查询的结点值:\n");
fflush(stdin);
scanf("%c",&a);
for(int i =0;i<tree.n;i++){
if(tree.tnode[i].data == a){
isfind=1;
int ad=tree.tnode[i].parent;
printf("%c的父节点为 %c,存储位置下标为 %d",a,tree.tnode[ad].data,ad);
break;
}
}
if(isfind == 0){
printf("树中无此节点");
}
}
int main()
{
PTree tree;
tree = InitPNode(tree);
FindParent(tree);
return 0;
}
2.孩子表示法
具体代码
#include<stdio.h>
#include<stdlib.h>
#define MAX_SIZE 20
#define TElemType char
//孩子表示法
typedef struct CTNode{
int child;//链表中每个结点存储的不是数据本身,而是数据在数组中存储的位置下标
struct CTNode * next;
}ChildPtr;
typedef struct {
TElemType data;//结点的数据类型
ChildPtr* firstchild;//孩子链表的头指针
}CTBox;
typedef struct{
CTBox nodes[MAX_SIZE];//存储结点的数组
int n,r;//结点数量和树根的位置
}CTree;
//孩子表示法存储普通树
CTree initTree(CTree tree){
printf("输入节点数量:\n");
scanf("%d",&(tree.n));
for(int i=0;i<tree.n;i++){
printf("输入第 %d 个节点的值:\n",i+1);
fflush(stdin);
scanf("%c",&(tree.nodes[i].data));
tree.nodes[i].firstchild=(ChildPtr*)malloc(sizeof(ChildPtr));
tree.nodes[i].firstchild->next=NULL;
printf("输入节点 %c 的孩子节点数量:\n",tree.nodes[i].data);
int Num;
scanf("%d",&Num);
if(Num!=0){
ChildPtr * p = tree.nodes[i].firstchild;
for(int j = 0 ;j<Num;j++){
ChildPtr * newEle=(ChildPtr*)malloc(sizeof(ChildPtr));
newEle->next=NULL;
printf("输入第 %d 个孩子节点在顺序表中的位置",j+1);
scanf("%d",&(newEle->child));
p->next= newEle;
p=p->next;
}
}
}
return tree;
}
void findKids(CTree tree,char a){
int hasKids=0;
for(int i=0;i<tree.n;i++){
if(tree.nodes[i].data==a){
ChildPtr * p=tree.nodes[i].firstchild->next;
while(p){
hasKids = 1;
printf("%c ",tree.nodes[p->child].data);
p=p->next;
}
break;
}
}
if(hasKids==0){
printf("此节点为叶子节点");
}
}
int main()
{
CTree tree;
tree = initTree(tree);
//默认数根节点位于数组notes[0]处
tree.r=0;
printf("找出节点 A 的所有孩子节点:");
findKids(tree,'A');
return 0;
}
3.孩子兄弟表示法
4.双亲孩子表示法
具体代码
#define MAX_SIZE 100
typedef char ElemType;
//孩子结点
typedef struct CTNode
{
int child;//孩子结点的下标
struct CTnode *next;//指向下一个孩子结点的指针
}*childptr;
//表头结构
typedef struct
{
ElemType data;//存放在树中的结点的数据
int parent;//存放双亲的下标
childptr firstchild;//指向第一个孩子的指针
}CTBox;
//树结构
typedef struct
{
CTBox nodes[MAX_SIZE];//结点数组
int r,n;
以上是树和二叉树的存储结构的知识,之后会更新树的遍历方式的相关内容。2020.8.17.