邓俊辉 数据结构 第二章 向量 笔记

抽象数据类型(接口与实现)

在这里插入图片描述在这里插入图片描述在这里插入图片描述

抽象数据类型(从数组到向量)

在这里插入图片描述在这里插入图片描述在这里插入图片描述
remove® 删除秩为r的元素并返回
disordered()返回逆序对的个数,本例中(4,3) (7,4) (9,6)
search® 返回不大于r 且秩最大的元素,假设-1号为负无穷

抽象数据类型(模板类)

在这里插入图片描述
在这里插入图片描述在这里插入图片描述
区间是前闭后开,所以相减就是区间长度

可扩容向量(算法)

在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
问题:是否可以将视频里向量扩容代码中的:

for (int i = 0; i < _size; i++) _elem[i] = oldElem[i];

替代为:

memcpy(_elem, oldElem, _size * sizeof(T));

答:如果T是简单数据类型(int、float、int*等),就没什么区别。如果T是复杂的类,并且重载了等号运算符,那么上面那行代码会调用等号运算符,是“深拷贝”;下面那行代码是“浅拷贝”。

可扩容向量(分摊)

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

无序向量(基本操作)

在这里插入图片描述
T & Vector::operator[](Rank r) { return _elem[r]; } 中的返回值T&是什么意义?
这是类型T的引用,使用它是因为返回值可以作为左值
在这里插入图片描述在这里插入图片描述
必须从前往后复制 否则会覆盖中间交叉的部分

无序向量(查找)

在这里插入图片描述在这里插入图片描述在这里插入图片描述

无序向量(去重)

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

无序向量(遍历)

在这里插入图片描述在这里插入图片描述

有序向量(唯一化)

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

有序向量(二分查找版本A)

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
技巧:统一写成<号,便于阅读
问题:在二分查找的版本A中,既然转向左右需要比较的次数不等,为什么不在进来时先进行e==A[mid]的判断,如果不等,然后再比较如果e(by oytf)
答:一般来说,相等是小概率事件。尽量让大概率事件的比较次数少,这样可以减少平均比较次数。(by yuantailing老师)
嗯,首先是概率。另外,判等的代价与比较差不多,把判等提前,相当于两个方向的成本变成2比2。虽然平衡了,但总体却增加了( by Junhui 老师)
在这里插入图片描述在这里插入图片描述在这里插入图片描述

有序向量(Fib查找)

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
问题:视频中给出的算法使用的是首先用O(lgn)的时间先生成一个fib数列,再继续在每次取得结果,既然在后面的数学计算中知道,这个结果是黄金分割比率为最佳,为什么不直接用mi = lo + (hi - lo)*0.6XXXX(黄金分割率)的直接获得呢?这样岂不是能减少很多的不必要的运算吗?(by Fankenst)
答:首先,两种方法复杂度都是logn,所以需要比较常数。生成fib序列用了logn次整数加法,用黄金分割率用了logn次浮点数乘法,后者慢一点。

其次,问题是离散化的,理论上是按fib数列分割最佳。推出按黄金分割比最佳是在“理想的连续情况”下,不存在。幸好对于任意fib数,黄金分隔法跟fib数列是一样的。

最后,无论是计算fib数列还是算浮点数乘法,这部分占的比例是微乎其微的:如果元素比较操作是复杂操作,那么只需要考虑元素比较次数就可以了;如果是简单操作,那么访存才是瓶颈,而不是计算。(by yuantailing老师)
问题:假设有一长度为6的向量(6不满足某一Fibnacci数-1的形式,而例题中的7是满足的,7=8-1),此时我分别用二分查找和Fibnacci查找分析了成功和失败的查找长度,发现两种分析方法的成功查找长度都是23/6,失败查找长度都是39/7. 所以我想问是不是只有满足我标题那种情况,Fibnacci查找才比二分查找效率要稍微高一点?(by 村上果树 )
答:计算各向量长度的平均成功查找长度、平均失败查找长度,如下表所示。

向量长度等于 fibnacci数 - 1 时,在平均查找长度的意义上,fib 查找的比二分查找(版本 A)更有优势;
向量长度比 fibnacci数 - 1 稍小一点时,因为分得没那么均匀了,因此 fib 查找的平均查找长度的优势没那么明显;
向量长度比 fibnacci数 - 1 稍大一点时,fib 查找会为了那 1 个多余的元素,整体多一层查找,查找长度反而比二分查找大。(by yuantailing老师)
问题:之前while查找,假设到n=hi-lo=fib.get()停止,轴点不应该是fib.prev()吗? 语句mi=lo+fib.get()-1=lo+n-1这么理解对吗?(by madajie9)
答:那么就是说,while终止时,fib.get()即为Fib[n−1],因为当为Fib[n]时循环判断条件hi-lo < fib.get()依然满足,所以继续fib.prev(),最后这个例子出while循环时fib.get()为Fib[n−1]。(by tyj956413282 )

有序向量(二分查找 版本B)

在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

有序向量(二分查找 版本C)

在这里插入图片描述在这里插入图片描述在这里插入图片描述

有序向量(插值查找)

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
log n固然是n的二进制位宽,但它具体代表什么,其实并不重要。这里只需要知道,当log n减到0的时候,问题被解决就够了。

之前的结论是,n不停地折半,需要log n次,问题可以被解决;现在可以利用这个结论,把n=log n带进去,log n不停地折半,需要log (log n)次,问题可以被解决。(by Jason214)在这里插入图片描述
大规模:插值查找
中规模:二分查找
小规模:顺序查找
问题:视频里说,对于大规模的情况下,可先用插值查找转化为中小规模的情况,对于中、小规模的情况而言,可以分别使用二分查找和顺序查找。那么前面所分析,顺序查找时间复杂度O(n),大于二分查找的时间复杂度 O(logn) ,那么有必要在这里对小规模的情况下推荐顺序查找吗?或者说对于小规模数据而言,顺序查找相比二分查找优势何在?谢谢(by tyj956413282)
答:折半查找 O(log n) 的常系数比顺序查找 O(n) 的常系数大,主要原因有:

折半查找里有一些计算
折半查找程序流程的分支比较多
折半查找访存不是顺序的,现代计算机系统结构都对顺序访问有更好的效率(by yuantailing老师)

向量(起泡排序)

在这里插入图片描述在这里插入图片描述
算法一旦检测有序就停止执行故复杂度是梯形而不是三角形
反例:前缀r 乱序,后缀有序
在这里插入图片描述在这里插入图片描述
该算法复杂度是跳跃的梯形
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
这是我以前做的,4个bs版本,第1个是最原始的,第2个,即Imp1,是比较常用的,后2个是教材上的代码,对3万个随机数,排序,多次测验,Imp1版本是最快的,写法也比较简明(by 不羁的逆袭)

递归排序(分而治之)

在这里插入图片描述在这里插入图片描述

归并排序(二路归并)

在这里插入图片描述在这里插入图片描述
将A数组copy给B数组时 视频用的 B[i] = A[i++] 在不同编译器中可能会产生错误效果 我使用的GCC 4.9.2 从右向左编译 那么i=0时 上面的表达式就会变成 B[1] = A[0] 会造成赋值错误 建议写成

for(i =0 ; i <lb;i++)
B[i] = A[i];
(by Binary621081) 在这里插入图片描述在这里插入图片描述在这里插入图片描述

归并排序(复杂度)

在这里插入图片描述在这里插入图片描述
问题:归并排序的复杂度是O(nlogn),也是稳定的,那涉及到排序统统都用归并排序不就是最好的吗?(by Tony284424 )
答:归并排序同时是Ω(nlogn)的,这意味着对于特殊形式的数据,可能别的算法花费O(n),归并排序仍要Ω(nlogn)。例如数据不是完全打乱的,是分段置乱的,起泡排序可能更快;
归并排序复杂度是O(nlogn),第12章学到快速排序,期望复杂度也是O(nlogn),但常数更小,因此在平均情况下也比归并排序更快;
以上是基于比较的排序。第9章学习桶排序、基数排序是O(n)的。(by yuantailing 老师)
归并排序最坏情况下时间复杂度、最好情况下时间复杂度、平均时间复杂度都是 Ω(nlogn) 。 它的空间复杂度是 O(n) 。

(by 闲人242545)

猜你喜欢

转载自blog.csdn.net/dldldl1994/article/details/86755359
今日推荐