数据结构之树和二叉树的存储结构(开篇3)

树的存储结构

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.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值