关于数据结构方面内容的简单回顾整理


1、线性表:a.数据类型相同,b.有限,c,序号唯一

2、线性表、顺序表、链表

线性表主要描述的是一一对应的相邻关系,是指逻辑结构

顺序表链表是指存储结构

以上两者是不同层面的概念

3、有序表也是一种逻辑结构,在插入问题上与线性表区分开来(线性表是任意插入,有序表还要在插入中维持有序性)

4、栈是逻辑结构(线性表)的一种,分为顺序栈(类似数组)和链栈,共享栈(这是啥啊)

5、栈的结构:有口的杯子-先进后出

6、队列同栈也是一种逻辑结构 ,不同在于其实一个管子-先进先出

7、树

节点的度:节点的子树个数

树的度:各节点度的最大值

性质1:数中节点数n等于所有节点的度加一(想象成一个一个火柴棒(头朝下的火柴棒)搭成一颗树,最后一个火柴棒上面还有个点点的。。。)

性质2:度为m的树种第i层上至多有m的i-1次方个节点(每个节点度都相同即均是最大度,就是此种极限情况)

还有两个性质,别记了,原理大概知道怎么算的就行了

父母兄弟孩子节点什么不说啦

8、二叉树

度为2的树,且区分左右子树

满二叉树:什么都不缺

完全二叉树:序号都不缺,可以理解为如果是层次遍历的话,那么至少在出现过的情况上,序号与满二叉树相同

9、二叉树遍历


先序遍历:ABDGHICEJKLMF

中序遍历:GDIHBAJMLKECF

后序遍历:GIHDBMLKJEFCA

递归算法

树的数据结构

typedef struct node

{

ElemType data;

struct node *Lchild;

struct node *Rchild;

}BTNode;

先序遍历

void PreOrder(BTNode *b)//递归开始节点为根节点

{

if(b != null)

{

cout<<b->data;

PreOrder(b->Lchild);

PreOrder(b->Rchild);

}

}

中序遍历

void InOrder(BTNode *b)//递归开始节点为根节点

{

if(b != null)

{

InOrder(b->Lchild);

cout<<b->data;

InOrder(b->Rchild);

}

}

后序遍历

void PostOrder(BTNode *b)//递归开始节点为根节点

{

if(b != null)

{

PostOrder(b->Lchild);

PostOrder(b->Rchild);

cout<<b->data;

}

}

层次遍历

书上写的什么啊,没看懂,把它当做图来思考,简单多了。。。


突然有个思考,那个过河卒问题中有关于图与树的思考  :m+n可以看做是树的高度,而路径个数就是在m+n深度上的子树个数

10、森林转换成二叉树

构造方法

a.在所有相邻兄弟节点之间加一个水平线

b.对每个非叶子节点,除了最左边的孩子节点外,删除k与其他孩子节点的连线

c.调整角度

11、二叉排序树

查找过程:递归过程--从根节点开始,如相等则查找成功,如大于则在左子树(右子树),反之(左子树)

构造过程:通过依次输入数据元素,并把他们插入到二叉树的适当位置--每读入一个元素,就新建一个节点,把新节点与当前树按查找过程进行比较,插入的适当的位置,有点像插入排序的思想

12、哈弗曼树(赫夫曼树)

由来--减少判定次数

又称最优树,一类带权路径长度最短的树(树的路径长度是从根节点到每个节点的路径之和)(wpl)

就是每个节点数值乘以所在深度值

构造方法(哈弗曼算法):

a.把每个节点看做一个独立的树

b.选取最小的两个作为一个树的左右子树,并把根节点权值设为两个子树的权值之和

c.在集合中删除上面两个子树,把根节点作为新树,放到集合之中

d.重复bc,知道集合中只有一棵树

哈弗曼编码:

由来--(电报编码)任何一个字符的编码都不是另一个字符编码的前缀-------尽可能短




后面都是一些经常碰到用到的内容,重要之处,不是几句话能说清楚地。。。

13.图

其他还好,经常接触到,最短路径有点晕,这个后面再整理,接触的少

14.查找

掌握两个就好,二分查找,二叉树查找

15.排序

简单排序O(n2)

冒泡、选择、交换

选择是不稳定的(有时候被看做稳定的,但这个稳定是有条件的,和算法有关,具体也见过,注意下)

进阶排序O(nlog2n)

快速、堆排序、二路归并排序

快速和堆排序是不稳定的

快速排序不能光说代码要会写哦(虽然是递归的,但是那个sign有点恶心)

简单说下各个排序吧

冒泡:(可以看做交换类排序的一种,快速排序是选择类排序的进阶)一种稳定的,平均时间复杂度是O(N2)的简单排序,基本思想是在一边排序中根据邻近元素的大小关系,进行依次交换,这样一轮排序后,就可以使本轮过程中最大或者最小的元素出现在正确的位置上,进而使得下趟遍历的范围减小,在这个过程中,“轻气泡上升,中气泡下降”,使元素逐渐趋近于正确的位置上,遍历的结束条件就是该趟遍历没有发生元素交换,对于多是正序的集合,较为适应。

选择:他的特异之处在于他的稳定性是由算法而定的。(举个例子,如果是aAbc,对其不缺分大小写进行排序,如果,是从后向前进行选择,那最终排序结果是稳定的,如果是从前向后排序,那么最终结果是不稳定的,好吧,到底什么可以称之为“正统”的选择排序呢,好吧,再深入想一点,如果对插入排序插入过程中查找顺序做一些变化的化,那么插入排序难道也要被看做不稳定的么,姑且把这种可以通过算法变稳定的排序称之为稳定排序吧)。从这个原理上几乎可以认为,堆排序是“选择”排序的一中了,那么上面的选择排序只是一种简单的选择方法了,而堆排序可以看做一种更加快捷的选择方法。

插入:也是一种稳定的,同冒泡,选择和插入一样都很好理解。但是插入排序有一种变种-----希尔排序,即先把集合分割成若干子序列,待其基本有序时候进行一次直接插入排序。(其中子序列是指间隔分割而成的,及时相当于12345--135-24(增量(间隔)为2),之类的分割,子序列之间的位置是无法串联的,最后一趟分割即相当于增量为1,另外希尔排序的好坏和增量的选取是相关的)

快速:基本思想是,在一趟排序中,把某元素作为关键字(一般为当前集合的第一个元素),从表的两端交替向中间扫描,在交互过程中,最终找到,关键字最终的位置,然后,再把由此关键字分割产生的两个集合,再进行上述过程,不断递归,直到记录中只有一个元素。(在这个过程中隐约感觉到一个二叉树的生成,对这个二叉树的中序遍历就是排序的结果啦啦啦)。另外,快速排序效率与关键字的选取有关,因为快速排序相当于一种从中间开始的双向冒泡法,所以关键字越靠近中间,那么效率越高,有时可以采用大致估算集合平均值来确定开始关键字,而不是机械的以第一个作为关键字(早就觉得以第一个做关键莫名其妙的,这样违背双向冒泡的思想么)(确定均值的方法可以采用随机抽样取均值的方法)

堆:基本思想就是,先构建一个基本有序堆,输出堆顶元素后,再对剩下的堆进行调整,最终得到一个有序序列

a.算法不是递归的,结束条件就是堆只剩下一个元素(此时堆,必然是有序的,但这里可以思考一下,是否可以参考一下冒泡排序,当不发生交换的时候,看做排序结束,这时候,中序遍历堆,就是一个有序序列了啊啊啊),此时遍历次数为堆的大小

b.调整一个堆采用交换比较好理解,那如何构建一个初始堆呢---------生成任意一个堆,堆这个堆从最后一个非终端节点元素,开始重复上面“筛选”过程,这个“非终端节点元素”是n/2(啊哈哈,这个n/2不是巧合哦,结合二叉树相关知识思考一下)。

c.这里还有个要注意的,就是这里所有所说的树结构其实是不存在的,其实本质上还是一个数组,只不过对应成了一个树结构,对应关系可以看做,有个节点下标为i,那么左右孩子节点为2*i+1,2*i+2。

二路归并:这个算法竟然是稳定的!!!哈哈,但不幸的是也是递归的。。。

关于排序的性能问题

三个简单排序的辅助存储都可以看做O(1)(不是递归的么,栈的深度为1),而进阶排序中快速排序O(logn),归并排序O(n)(归并排序这个坑爹孩子,那么大的递归深度(栈深度),需要那么多辅助存储空间,数据大点就太坑了),奇葩的是堆排序不是递归的,辅助存储和简单排序相同,但是堆排序过程中要进行大量比较,这使得实际中归并较堆排序快一点(如果把我说的,堆排序结合冒泡的终止条件,是不是能快那么一点点呢)。对于三个简单排序,对于基本有序序列,冒泡和插入较快捷,其中插入算法常与其他进阶排序结合使用(估计是其他排序在排成基本有序后,用插入法搞定之),而作为简单交换排序方法------冒泡法进阶的快速排序就“偏爱”基本有序情况,其性能取决于关键字的选取(上面提到过一些)。

16、关于那些乱七八糟排序为什么会性能不同的一点乱七八糟的思考

a.快排为什么比冒泡快——这个原理有点像二分查找啊,如果关键字选在相对中间的话,那么就相当于无形中减少了每次遍历结合的范围,这些范围就相当于周长和面积的关系,虽然长度综合不变,但是一个大大的长度,圈起来的土地要比把这个长度分割开圈起来得土地小很多的

b.快排为什么会需要辅助存贮空间——不要说因为他是分叉递归的,(运用二叉树层次遍历的思想,完全可以把这货写成一个非递归的算法),这只是表象,本质应该是在于,如果我采用了上面所说的,本人臆测的所谓二叉树层次遍历思想的非递归的快速排序方法的话————————,那么我是不是需要一些存储空间去记录这个树的机构呢,这些记录信息,恰巧就是这个算法的辅助存贮空间啊,好吧,还是用分叉递归吧,存在即合理果然是真理

c.为啥我感觉插入和冒泡会比,选择排序快些———在插入和冒泡排序的进行过程中,都是对排序信息进行了一定的存储的(如冒泡法,是每个元素的位置对正确位置开始了逼近,插入过程中,被插入的集合石有序性的,无形中减少了比较次数。。。)。

d.为啥会有进阶算法——这些进阶算法,说白了都是在排序过程中,上一次排序中对下次排序可以能有用的信息进行了存储,如快排中:一分为二,减少每个“冒泡区间大小”,堆排序中:构建初始堆,相当于提前对数据做了一部分类似图形学中(拓扑运算的处理)(我感觉堆排序不是一个纯粹的单一排序,更像一个生成基本有序序列后在用插入排序的复合排序)。

e.排序算法的性能和时间复杂度和辅助存储空间的关系——有关系,但不是绝对的,时间复杂度相当于做思考的个数,如果一次思考的时间过长,那么即使思考次数较小,也会使总时间延长,这样就使得,排序算法中,比较次数和交换次数也影响到了效率问题(好吧,具体还没认真想过)。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值