数据结构之树的存储结构

  1. 树是一种一对多的数据结构,这个一对多很好解释,就比如一只狗妈妈,会有多只小奶狗,这不就有一对多的意思吗!

  2. 树的根节点有且只有一个,就比如小奶狗们只有一个亲狗妈。

    在这里插入图片描述

  3. 那么图上的 B C D E 都是树的根节点 A 的孩子; 总之,树就是有很多结点构成,只不过这些结点在树中会有不同的称呼,来分析一下下图

    在这里插入图片描述

  4. 度----结点拥有的子树数称为结点的度, 度为 0 的结点称为树的叶结点;树的度是树内结点的度的最大值;此树的度为 3 。

  5. 树中结点之间的关系都是表达在字面上的,比如 B 是 A 的左孩子, C 是 A 的有孩子,A 是它们的双亲, 接下来的以此类推, 这关系还有堂兄弟关系、祖宗关系等。

  6. 树的深度(高度)就是树中结点的最大层次,比如上图中根结点 A 为第一层, 根的孩子们为第二层,以此类推,此树的深度为 5 。

  7. 有许多的集合在一起就可以形成森林。

树的存储结构

存储结构基本上就是顺序存储和链式存储这两种,然而对于树这种一对多的结构,用这两种存储结构更便利,产生主要的三种存储结构表示法:双亲表示法、孩子表示法、孩子兄弟表示法。

1. 双亲表示法

其实双亲表示法内部主要还是以顺序存储为主
先来看看该表示法的图吧(来源于《大话数据结构》)

在这里插入图片描述

特点:

  • 根结点是没有双亲,根结点的位置位置域为-1
  • 根据结点的parent指针很容易找到它的双亲结点。所用时间复杂度为O(1),直到parent为-1时,表示找到了树结点的根。
  • 找到孩子结点,需要遍历整个结构。

代码

	#include <stdio.h>
	#define MAX_TREE_SIZE 100
	typedef char ElemType;
	typedef struct PTNode
	{
	    ElemType data;
	    int parent;
	}PTNode;
	
	typedef struct
	{
	    PTNode nodes[MAX_TREE_SIZE];
	    int n;   //This is number of the node
	}PTree;
	
	void creat_PNode(PTree *tree)
	{
	    char c;
	    int index;
	    printf("Please enter the numbers of node: ");
	    scanf("%d", &(tree->n));
	
	    printf("Please enter value of the node, and the positon of parent nodes in the array: \n");
	    for(int i = 0; i < tree->n; i++)
	    {
	        getchar();
	        scanf("%c %d", &c, &index);
	        tree->nodes[i].data = c;
	        tree->nodes[i].parent = index;
	    }
	}
	
	void find_Parent(PTree tree)
	{
	    char c;
	    int flag = 0;
	    printf("Please enter vlaue of node to be finded: ");
	    getchar();
	    scanf("%c", &c);
	    for (int i = 0; i < tree.n; i++)
	    {
	        if (tree.nodes[i].data == c)
	        {
	            flag = 1;
	            int parent_Int = tree.nodes[i].parent;
	            printf("%c of parent node is %c , the parent node`s location subscript is %d", c, tree.nodes[parent_Int].data, parent_Int);
	        }
	    }
	
	    if (flag == 0)
	    {
	        printf("It has not the node about %c in the tree!\n", c);
	    }
	}
	
	int main()
	{
	    PTree tree;
	    creat_PNode(&tree);
	
	    find_Parent(tree);
	    return 0;
	}

2.孩子兄弟表示法

定义:把每个结点的孩子结点排列起来,以单链表作为存储结构,则n个结点有n个孩子链表,如果是叶子结点则此单链表为空。然后n个头指针又组成一个线性表,采用顺序存储结构,存放进一个一维数组中。
来个图吧
在这里插入图片描述

代码

#include <stdio.h>
#include <stdlib.h>
#define MAX_TREE_SIZE 100
typedef char ElemType;
typedef struct CTNode  //child node
{
    int child;
    struct CTNode *next;
}*ChildPtr;
typedef struct //Head structure
{
    ElemType data;
    ChildPtr firstchild;
}CTHead;
typedef struct
{
    CTHead node[MAX_TREE_SIZE];
    int n; //The numbers of node
   // int r; //The position of root of the tree    The root node of the default tree is at the array node[0]
}CTree;

void creat_Tree(CTree *tree)
{

   printf("Please enter the number of node: ");
   scanf("%d", &(tree->n));
   for (int i = 0; i < tree->n; i++)
   {
       printf("Please enter value of %dth node: ", i + 1);
       getchar();
       scanf("%c", &(tree->node[i].data));
       tree->node[i].firstchild = (ChildPtr)malloc(sizeof(CTNode));
       tree->node[i].firstchild->next = NULL;

       printf("Please enter the number of child node of node \'%c\' :", tree->node[i].data);
       int num = 0;
       scanf("%d", &num);

       if (num != 0)
       {
           ChildPtr p = tree->node[i].firstchild;
           for (int j = 0; j < num; j++)
           {
               ChildPtr pNew = (ChildPtr)malloc(sizeof(CTNode));
               pNew->next = NULL;
               printf("Please enter the position of the %dth child node in the sequence table : ", j + 1);
               scanf("%d", &(pNew->child));
               p->next = pNew;
               p = pNew;
           }
       }
   }

}

void find_Tree(CTree tree)
{
    char c;
    int flag = 0;
    printf("You need to find out which node`s child node : ");
    getchar();
    scanf("%c", &c);

    for (int i = 0; i < tree.n; i++)
    {
        if (c == tree.node[i].data)
        {
            ChildPtr p = tree.node[i].firstchild->next;
            while(p)
            {
                flag = 1;
                printf("%c ", tree.node[p->child].data);
                p = p->next;
            }
            printf("\n");
            break;
        }
    }
    if (flag == 0)
    {
        printf("%c node is leaf node\n", c);
    }

}

int main()
{
    CTree tree;
    creat_Tree(&tree);

    find_Tree(tree);
    return 0;
}

3.孩子兄弟表示法

定义:任意一棵树,它的结点的第一个孩子如果存在就是唯一的,它的右兄弟存在也是唯一的。因此,设置两个指针,分别指向该结点的第一个孩子和此结点的右兄弟。

结构定义:

	#define MAX_TREE_SIZE 100
	typedef int  ElemeType;
	
	typedef struct CSNode{
	    ElemeType data;
	    struct CSNode * firstchild;   //存储该结点的第一个孩子的存储地址
	    struct CSNode * rightsib;  //存储该结点的右兄弟结点的存储地址
	    
	}CSNode, *CSTree;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值