数据结构3-1:树与树的表示

什么是树?

像我们平时使用的U盘,里面的目录和子目录之间的关系就是有层次关系的树。

顺序查找:(哨兵的设立)

说明:
下标为0的位置不是我们要查找的数据,而是我们所设立的哨兵,我们要查找的数据是在Element[1]~Element[10]之间查找的。建立哨兵还有一个作用就是防止数组下标越界,也就是不需要添加i>0的条件了。当从Element[10]开始找,找到Element[1],如果还没有找到,再往上找就碰到了Element,此时设置的哨兵就拦截了,停止查找。这样也防止了每一次循环就要去判断是不是到达了数组边界的问题。通过哨兵,再循环的时候就少写一个判断分支。


我们最终循环结束,得到一个i返回值,通过判断i值,我们就可以知道是否查找到了,如果k!=0,那么就是在Element[10]~Element[1]之间找到了K值,找到了我们需要查找到的值。
但是如果K=0,那么就是找到了哨兵,在Element[10]~Element[1]之间没有查找到我们想要的值。没查找到我们需要的值。

显然,这样查找的效率并不高,那有没有效率高的查找方法呢?
有————————二分查找!

二分查找:

二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。

left>right,发生了left、right边界错位,所以查找失败,结束。

说明:
1、上面的树中的数字都代表所查找元素的下标
2、ASL:表示平均查找长度。

我们能不能把数据不一定放在数组当中,就按照这样(上图)一个层次化的结构来存储我们的数据,是不是也会达到二分查找的效果?
这就是我们后面要讲的:我们用树的形式来存储我们需要的数据,使得我们的一些查找过程更加方便————查找树!
查找树和二分查找的效率上可以得到差不多的效果都是log2n(log以2为底)。

树的定义:

树是保证结点联通的最小的一种连接方式(边最少的连接方式),因为随便删去树中的一条边,就整体就不是一颗树了。

树的表示:

上面这种表示方法我们发现有三个指针域的,有两个指针域的,还有一个指针域的,那么整个结构的形式不一样,会给我们后面的程序实现带来困难。

但是如果将上面的结构统一设置成都有三个指针域,那这样结构就统一了,但是,这样又造成了大量的空间浪费问题,因为时间上,我们的边只有n-1条边,但是都使用3个指针域的话,那么就会造成3n-(n-1)=2n+1个指针的空间浪费。

儿子–兄弟表示法

第一个指针域FirstChild:表示的是“长子”,即第一个孩子结点(子节点)。

第二个指针域:NextSibling:表示的是它的下一个兄弟结点。

我们发现这样的结构每一个结点都有两个指针域,只造成了2n-(n-1)=n+1个指针域的浪费,浪费的空间也不算大。

代码:

typedef struct TNode *Position;
typedef Position BinTree; /* 二叉树类型 */
struct TNode{ /* 树结点定义 */
    ElementType Data; /* 结点数据 */
    BinTree Left;     /* 指向左子树 */
    BinTree Right;    /* 指向右子树 */
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱睡觉的小馨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值