码迷,mamicode.com
首页 > 其他好文 > 详细

树结构存储表示

时间:2020-02-18 18:15:50      阅读:73      评论:0      收藏:0      [点我收藏+]

标签:遍历   blog   链式存储结构   表示   space   ace   多个   init   null   



对于双亲表示法:我们先将双亲结点存入,我们每插入一个结点都是知道双亲结点位置的,数据可以直接插入。使用顺序存储结构更加方便 而对于孩子表示法,我们每次插入一个结点,对其子树的位置存放暂不确定,所有使用链式存储结构占主要

(一)双亲表示法

以双亲作为索引的关键词的一种存储方式
每个结点只有一个双亲,所以选择顺序存储占主要
以一组连续空间存储树的结点,同时在每个结点中,附设一个指示其双亲结点位置的指针域
结点:
技术图片

 


 

#include<iostream>
#include<cstring>
const int MAXN=100;
using namespace std;

struct node
{//双亲表示法. 
    char val;//
    int par;//父亲 
};
node L[MAXN];
int length;
bool vis[MAXN];
void print(int root)
{//这个程序不用担心产生环. 
    if(root<length)
    {
        cout<<L[root].val<<" "; vis[root]=true;
        for(int i=0;i<length;i++)
            if(!vis[i]&&L[i].par==root) print(i);
       //这个地方是有瑕疵的,其实不必有vis的判断,因为树本身的性质决定了它不可能存在图的遍历中可能存在的环,也就排除了重复访问的可能性. }
return ; } void init(int n) { for(int i=0;i<n;i++) L[i].par=-1,vis[i]=false; } int main() { int n; char chx,chy; cin>>n; length=n; init(n); for(int i=0;i<n-1;i++) { int x,y; cin>>x>>chx>>y>>chy; L[x].val=chx; L[y].val=chy; L[y].par=x; } print(0); return 0; } /* 10 0 a 1 b 0 a 2 c 1 b 3 d 3 d 6 g 3 d 7 h 3 d 8 i 2 c 4 e 2 c 5 f 4 e 9 j a b d g h i c e j f */

 

其实以上的双亲表示法虽然简单,但是也是有缺陷的,那就是在短时间内不容易快速写出.如何才能快速写出呢?

  int par[maxn];//par[i]表示i结点的父亲下标     int val[maxn];//val[i]表示i结点对应的值.  

以上代码即可.

二.孩子表示法.
 1 #include<iostream>
 2 #include<cstring>
 3 using namespace std;
 4 
 5 //孩子表示法;
 6 //即每个树结点都有孩子索引域 
 7 
 8 struct node
 9 {//degree=2
10     char val;
11     int left,right;
12 }a[1001];
13 int n;
14 void init()
15 {
16     for(int i=0;i<n;i++) a[i].val=1,a[i].left=a[i].right=-1;
17 }
18 
19 void print(int root)
20 {
21     if(root<n)
22     {
23         cout<<a[root].val<<" ";
24         if(a[root].left!=-1) print(a[root].left);
25         if(a[root].right!=-1) print(a[root].right);
26     }
27     return ;
28 }
29 
30 
31 int main()
32 {
33     int cnt=0,x,y;
34     char chx,chy;
35     cin>>n;
36     init();
37     while(1)
38     {
39         if(cnt==n-1) break;
40         cin>>x>>chx>>y>>chy;
41         a[x].val=chx; a[y].val=chy; 
42         if(a[x].left==-1) a[x].left=y;
43         else a[x].right=y;
44         cnt++; 
45     }
46     print(0);
47     return 0;
48 }

以上就是孩子表示法,其实这是有很大瑕疵的,因为一个结点不容易找到它的爹,所以我们可以在结点的内部增加一个域用以表示其父亲也是可以的

正如:

1 struct node
2 {//degree=2
3     char val;
4     int par;
5     int left,right;
6 }

其实这样的改进也是不太好的.

为什么呢?

你怎么知道树的度是多少呢?

那如何呢?

看下面:

1 struct node
2 {//degree=2
3     char val;
4    int par;
5 int child[max_degree]; 6 }

看吧,儿子好找了,爹也好找了.但是我们看,这...是不是太浪费空间了?

如何优化呢?

不急,看图.

技术图片

 

 

两种线性表的结合是不是很不错呢?
具体怎么运用呢?
自己琢磨去!

三.孩子兄弟法.
下面就是孩子兄弟法了,具体是:
1 struct node
2 {
3     char val;
4     node *firstchild,*next_sibling;
5 };
可以看出,结点的内容是存储每一个结点的第一个孩子以及此结点的兄弟.
可以看出,我们既优化了每个父亲对多个孩子的索引的简化,又能使得每个结点可以轻松的访问它的众多兄弟,
其实在xpath和dom树中对结点的兄弟的获取就是靠着这种结构而构造成的.

代码为:

 1 #include<iostream>
 2 #include<cstring>
 3 using namespace std;
 4 
 5 //孩子表示法;
 6 //即每个树结点都有孩子索引域 
 7 struct node
 8 {
 9     char val;
10     node *firstchild,*next_sibling;
11 }a[1001];
12 int n;
13 void init()
14 {
15     for(int i=0;i<n;i++) a[i].val=1,a[i].firstchild=a[i].next_sibling=NULL;
16 }
17 
18 void print(node *root)
19 {
20     if(root!=NULL)
21     {
22         cout<<root->val<<" ";
23         node* temp=root->firstchild; 
24         while(temp)
25         {
26             print(temp);
27             temp=temp->next_sibling;
28         }
29     }
30     return ;
31 }
32 
33 
34 int main()
35 {
36     int cnt=0,x,y;
37     char chx,chy;
38     cin>>n;
39     init();
40     while(1)
41     {
42         if(cnt==n-1) break;
43         cin>>x>>chx>>y>>chy;
44         a[x].val=chx; a[y].val=chy; 
45         if(!a[x].firstchild) a[x].firstchild=&a[y];
46         else
47         {
48             node * temp=a[x].firstchild,*fa=NULL;
49             while(temp) fa=temp,temp=temp->next_sibling;
50             fa->next_sibling=&a[y];
51         }
52         cnt++; 
53     }
54     print(&a[0]);
55     return 0;
56 }

以上就是这三种基本的树的存储结构,

里面还掺杂了一些优化缘由(无非是为了满足我们的某种需求而需要设计较好的数据结构)

以及优化后的结果.

其中三段大代码的输入数据都是一样的.

且结点的数据结构都是靠着数组来设计的.

好了,关于树的存储也告一段落了.

欢迎批评指正.

以下是两份我觉得写的很不错的博文.值得参考.
https://www.cnblogs.com/jpfss/p/10842521.html  梗概
https://www.cnblogs.com/ssyfj/p/9459887.html  优化.

树结构存储表示

标签:遍历   blog   链式存储结构   表示   space   ace   多个   init   null   

原文地址:https://www.cnblogs.com/zww-kjj/p/12325446.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!