数据结构基础部分

数据:是对客观事物的符号表示,在计算机科学中是指所有能输入到计算机中并被计算机程序处理的符号总称。(计算机程序加工的原料)

数据元素:是数据的基本单位,在计算机程序中通常作为一个整体进行考虑和处理。

数据对象:是性质相同的数据元素的集和,是数据的一个子集。

数据结构:是相互之间存在一种或多种特定关系的数据元素的集和(一种简单解释)。数据之间的相互关系称为结构

根据数据元素之间关系的不同特性,通常有下列4类基本数据结构:

  1. 集和:结构中的数据元素之间除了“同属于一个集和”的关系外,别无其他关系;
  2. 线性结构:结构中的数据元素之间存在一个对一个的关系
  3. 树形结构:结构中的数据元素存在多个对多个的关系
  4. 图形结构或网状结构:结构中的数据元素存在多个对多个的关系

数据结构在计算机中的表示称为数据的物理结构,又称存储结构,数据元素在计算机中有两种不同的表示方法:顺序映像非顺序影响对应两种存储结构:顺序存储结构链式存储结构

算法:是对特定问题求解步骤的一种描述,它是指令的有限序列,其中每一条指令表示一个或多个操作;此外,一个算法还具有下列5个重要特性:

  1. 有穷性:一个算法必须总是(对任何合法的输入值)在执行有穷步之后结束,且每一步都可在有穷时间内完成。
  2. 确定性:算法中每一条指令必须有确切的含义,读者理解时不会产生二义性。并且,在任何条件下,算法只有唯一的一条执行路径,即对于相同的输入只能得出相同的输出。
  3. 可行性:一个算法是能行的,即算法中描述的操作都是可以通过已经实现的基本运算执行有限次来实现的。
  4. 输入:一个算法有零个或多个输入,有些输入取自于某个特定的对象集和。
  5. 输出:一个算法有一个或多个输出,这些输出是与输入有某些特定关系的量。

算法设计的要求:

  1. 正确性
  2. 可读性
  3. 健壮性
  4. 效率与低存储量需求

算法效率的度量

T(n)=O(f(n))

表示随问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称做算法的渐近时间复杂度,简称时间复杂度
算法的存储空间需求
类似于时间复杂度,空间复杂度作为算法所需存储空间的量度

S(n)=O(f(n))
线性表:n个数据元素的有限序列

线性表有顺序存储(连续的存储空间),链式存储(任意的存储单元存储线性表的元素)两种存储结构

:是限定在表尾进行插入或删除操作的线性表,表尾称为栈顶,表头称为栈底。又称为后进先出(LIFO)的线性表
队列:队列是一种先进先出(FIFO)的线性表。在队列中,允许插入的一端叫做队尾,允许删除的一端则称为对头
在这里插入图片描述

(或字符串)是由零个或多个字符组成的有限序列,一般记为
s = ‘a1a2…an’ (n>=0)
串中字符的数目n称为串的长度。零个字符的串称位空串,长度为0.
称两个字符串是相等的,当且仅当这两个串的值相等。也就是说,只有两个串的长度相等,并且各个对应位置的字符都相等才相等。

数组一般不作插入或删除操作,一旦建立了数组,结构中的数据元素个数和元素之间的关系就不再发生变动。所以一般采用顺序存储

广义表

顾名思义,广义表是线性表的推广。也有人称为列表(lists,用复数形式以示与统称的表list的区别)
广义表一般记作
LS = (α1,α2,…,αn)
在线性表的定义中,α1(1<=i<=n)只限于是单个元素。而在广义表的定义中,αi可以是单个元素,也可以是广义表,分别称为广义表的原子子表

当广义表为非空时,称第一个元素α1为LS的表头(Head),称其余元素组成的表(α2,α3,…,αn)是LS的表尾(Tail)。

广义表的存储结构
由于广义表(α1,α2,…,αn)中的数据元素可以具有不同的结构(或是原子,或是列表),因此很难用顺序存储结构表示,通常采用链式存储结构,每个数据元素用一个节点表示。

在这里插入图片描述
由于列表中的数据元素可能为原子或列表,由此需要两种结构的结点:一种是表结点,用以表示列表;一种是原子结点,用以表示原子。若列表不为空,则可分解为表头和表尾;反之,一对确定的表头和表尾可唯一确定列表。由此,一个表结点可由3个域组成:标志域,指示表头的指针域,指示表尾的指针域;而原子结点只需两个域:标志域和值域。

树是n个结点的有限集。在任意一个非空树中:(1)有且仅有一个特定的称为根的结点;(2)当n>1时,其余结点可分为m(m>0)个互不相交的有限集T1,T2,…,Tm,其中每一个集和本身又是一棵树,并且称为根的子树
:结点拥有的子树称为结点的度。
叶子终端结点:度为0的结点
非终端结点分支结点:度不为0的结点

一个结点的子树的跟称为该结点的孩子,相应的该结点称为孩子的双亲,同一个双亲的孩子之间互称兄弟

结点的祖先是从根到该结点所经分支上的所有结点。反之,以某结点为根的子树中的任一结点都称为该结点的子孙

结点的层次从根开始定义起,根为第一层,根的孩子为第二层。双亲在同一层的结点互称为堂兄弟
树种结点的最大层次称为树的深度或高度。

如果将树中结点的各子树看成从左至右是有次序的(即不能互换),则称该树为有序树,否则称为无序树
森林是m(m>=0)棵互不相交的树的集和。

二叉树:每个结点至多只有两棵子树(即二叉树中不存在度大于2的结点),并且,二叉树的子树有左右之分,其次序不能任意颠倒。
二叉树的性质

  • 在二叉树的第i层上至多有2的i-1次方个结点(i>=1)。

  • 深度为k的二叉树至多有(2的k次方)-1个结点(k>=1).

  • 对于任何一棵二叉树T,如果其终端结点树为n0,度为2的结点树为n2,则n0=n2+1。

  • 具有n个结点的完全二叉树的深度为⎣log2 n⎦+1 。(⎣log2 n⎦表示不大于log2 n的最大整数)。

  • 如果对一棵有n个结点的完全二叉树(其深度为⎣log2 n⎦+1)的结点按层序编号,则对任一结点i(1<=i<=n),有:

     		 1. 如果i=1,则结点i无双亲,是二叉树的根;如果i>1,则其双亲的编号是 i/2(整除)。
     		 2. 如果2i>n,无左孩子;否则,其左孩子是结点2i。
     		 3. 如果2i+1>n,则结点i无右孩子;否则,其右孩子是结点2i+1。
    

二叉树的遍历

  • 先序遍历
    若二叉树为空,则空操作;否则
    1.访问根节点 2先序遍历左子树 3先序遍历右子树

  • 中序遍历
    若二叉树为空,则空操作;否则
    1.中序遍历左子树 2.访问根节点 3.遍历右子树

  • 后序遍历
    若二叉树为空,则空操作;否则
    1.先序遍历左子树 2.后序遍历右子树 3.访问根结点

在这里插入图片描述

此二叉树先序序列为 ➖➕a✖b➖cd / ef
中序序列为 a➕b✖c➖d➖e / f
后序序列 abcd➖✖➕ef / ➖
线索二叉树
在这里插入图片描述
LTag=0 lchild域指示结点的左孩子 LTag=1 lchild域指示结点的前驱
RTag=0 rchild域指示结点右孩子 RTag=1 rchild指示结点的后继

这种指示来源于线索二叉树规则:若结点有左子树,则其lchild域指示其左孩子,否则令lchild域指示其前驱;若结点有右子树,则其rchild域指示其右孩子,否则令rchild域指示其后继。
在这里插入图片描述
上图为线索二叉链表

赫夫曼树

一些概念

  • 路径:从一个祖先结点到子孙结点之间的分支构成这两个结点间的路径;
  • 路径长度:路径上的分支数目称为路径长度;
  • 树的路径长度:从根到每个结点的路径长度之和。
  • 结点的权:根据应用的需要可以给树的结点赋权值;
  • 结点的带权路径长度:从根到该结点的路径长度与该结点权的乘积;
  • 树的带权路径长度=树中所有叶子结点的带权路径之和;通常记作 WPL=∑wi×li
  • 哈夫曼树:假设有n个权值(w1, w2, … , wn),构造有n个叶子结点的二叉树,每个叶子结点有一个 wi作为它的权值。则带权路径长度最小的二叉树称为哈夫曼树。最优二叉树。

在这里插入图片描述
树1:WPL=72+52+22+42=36
树2:WPL=73+53+21+42=46
树3:WPL=71+52+23+43=35
则树3的WPL最小。树3其实是赫夫曼树
2+4=6 6与5构造新树 6+5=11 11只能与7构造新树了。

二叉排序树(又称二叉排序树)
概念:二叉排序树或者是一棵空树;或者是具有下列性质的二叉树:(1)若它的左子树不空,则左子树上所有结点的值均小于它的根节点的值;(2)若它的右子树不空,则右子树上所有结点的值均大于它的根节点的值;(3)它的左、右子树也分别为二叉排序树。

二叉排序树的构造

现有序列:61 87 59 47 35 73 51 98 37 93
构造过程如下:
1)索引 i = 0,A[i] = 61,结点61作为根结点,如图:
在这里插入图片描述
2)索引 i = 1,A[1] = 87, 87 > 61,且结点61右孩子为空,故81为61结点的右孩子,如图:

在这里插入图片描述
3)索引 i = 2,A[i] = 59,59 <
61,且结点61左孩子为空,故59为61结点的左孩子,如图
在这里插入图片描述
4)索引 i = 3,A[3] = 47,47 < 59,且结点59左孩子为空,故47为59结点的左孩子,如图
在这里插入图片描述
5)索引 i = 4,A[4] = 35,35 < 47,且结点47左孩子为空,故35为47结点的左孩子,如图
在这里插入图片描述
采用同样规则遍历整个数组得到如图2.6所示的一棵排序二叉树。
在这里插入图片描述
二叉排序树查找
由二叉树的递归定义性质,二叉排序树的查找同样可以使用如下递归算法查找。

如果树是空的,则查找结束,无匹配。
如果被查找的值和根结点的值相等,查找成功。否则就在子树中继续查找。如果被查找的值小于根结点的值就选择左子树,大于根结点的值就选择右子树。

在理想情况下,每次比较过后,树会被砍掉一半,近乎折半查找。
遍历打印可以使用中序遍历,打印出来的结果是从小到大的有序数组。
二叉排序树插入
二叉排序的插入是建立在二叉排序的查找之上的,插入一个结点,就是通过查找发现该结点合适插入位置,把结点直接放进去。 其实在2.2节中一步步构造二叉排序树的过程中就是结点插入过程。由此可以得出二叉排序树插入规则如下:

若查找的key已经有在树中,则p指向该数据结点。
若查找的key没有在树中,则p指向查找路径上最后一个结点。

例如:若在图2.6展示的二叉排序树中插入结点数据为60的结点。
首先查找结点数据为60的结点,二叉排序树中不存在结点为60的结点,因此查找失败。此时查找指针p指向查找路径最后一个结点即指向59结点。由于60>59且59结点右子树为空,故将60结点作为59结点的右孩子,插入完成。插入后的二叉排序树如图2.8所示。
在这里插入图片描述
二叉排序树删除
删除的时候需要考虑以下几种情况:

1)删除结点为叶子结点;
2)删除的结点只有左子树;
3)删除的结点只有右子树
4)删除的结点既有左子树又有右子树。

对于前三种情况直接删除
第四种情况对于待删除结点既有左子树又有右子树的情形,最佳办法是在剩余的序列中找到最为接近的结点来代替删除结点。这种代替并不会影响到树的整体结构。那么最为接近的结点如何获取呢?

可以采用中序遍历的方式来得到删除结点的前驱和后继结点。选取前驱结点或者后继结点代替删除结点即可。

例如:待删除的结点为47,图2.8中二叉排序树的中序遍历序列为35 37 47 51 59 60 61 73 87 93 98。则结点47的前驱结点为37,则直接将37结点替代47结点即可。替换后的二叉排序树如图2.11所示:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值