【015】Python全栈日记-查找和排序

一、查找

1、查找概念

假设有两组数据:

int array1[]={6,4,5,3,8,7,1,2,0,9};

int array2[]={0,1,2,3,4,5,6,7,8,9};

 

一个有序数组,一个无序数组, 在他们之间查找某一个值的方法有什么区别呢,

 

对于两组数据我们都可以用最直接的方法,逐个比较直到遇到合适的值。

 

1、顺序查找

第一种方法从表中最后一个记录开始,逐个进行记录的关键字和给定值的比较,若某个记录的关键字和给定值比较相等,则返回返回记录所在的位置,或查找完所有记录后还没有发现符合的记录,则查找失败。我们称其为顺序查找。

 

通过python实现一下:

结果:

 

2、折半查找

当数据是一个有序的情况时,我们可以利用这样一种思路:与记录中间值比较,如果比中间值小去左边查,否则去右边查找,直到找到为止,区域内没记录时查找失败。

 

对于给定key值,逐步确定待查记录所在区间,每次将搜索空间减少一半(折半), 直到查找成功或失败为止。我们称其为折半查找。

 

通过python来实现一下:

Low和high是最小的数和最大的数的下标,mid是中间数的下标,mid取整,如果要找的数小于mid 则在下标位low和mid-1之间的数查找,如果要找的数大于mid 则在下标位mid+1和high之间的数查找,以此类推。

 

结果:

 

3、递归折半

折半查找还可以通过使用递归的方法来完成,直接通过返回给函数修改后的low或者high来完成查找。因为通过递归来循环这个过程所以不需要使用while,只需要用if限制一下不要让low大于high。

结果:

 

 

排序的分类:排序分为插入排序、选择排序、交换排序、归并排序四大类。

 

 

二、算法复杂度

在进行算法分析时,语句中的执行次数T(n)是关于问题规模n的函数,进而分析T(n)随n的变化情况并确定T(n)的数量级。算法的时间复杂度,也就是算法的时间量度,记作:T(n)=O(f(n))。它表示随问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称作算法的渐近时间复杂度,简称为时间复杂度。其中f(n)是问题规模n的某个函数。

一般情况下,随着n的增大,T(n)增长最慢的算法为最优算法。

 

定义:O(1)叫做常数阶、O(n)叫线性阶、O(n2)叫平方阶。

 

三、排序稳定性

 稳定排序:对于关键字相等的记录,排序前后相对位置不变。

 不稳定排序:对于关键字相等的记录,排序前后相对位置可能发生变化。

 

四、交换排序-冒泡法

冒泡排序是经典的排序方法,思想简单,操作容易,算法稳定性好。是排序的基础算法,学习它有很大的必要性。

 

思想:相邻记录比较,如果逆序(前大后小)则交换,这样一趟排序会使最大(最小)的记录落到最后,这称之为一趟排序。N个记录需要N-1趟排序。

 

1、冒泡排序算法

关键字序列 T=(21,25,49,25*,16,08),请写出冒泡排序的具体实现过程。

初态: 21,25,49, 25*,16,  08

第1趟:21,25,25*,16, 08 , 49

第2趟:21,25, 16, 08 ,25*,49

第3趟:21,16, 08 ,25, 25*,49

第4趟:16,08 ,21, 25, 25*,49

第5趟:08,16, 21, 25, 25*,49

 

通过画图来了解一下思路,‘

第一趟,21和25对比,不变。25和49对比,不变。49和25*对比,调换位置。49和16对比,调换位置。49和08对比,调换位置。最大数49已经被放在最后。第二趟最后就不用在和49对比。

接下来几趟和第一趟方法一致。

通过python来实现:

结果:

[1, 2, 3, 4, 5]

 

2、优化

我们发现每趟交换时,只需要交换那些不是挪到最后的数

对于a=[5,4,3,2,1]

第一趟,我们交换4次就可以。

第二趟,我们只需要交换3次

第三趟,我们只需要交换2次

第四趟,我们交换1次就完成了排序。

通过这个我们能发现规律:交换次数等于a的长度减去趟数。

那我们优化一下代码:

 

3、冒泡法复杂度分析

最好的情况当记录完全有序时,只需要n次比较,发现在这一趟中没有数据交换,则排序停止,记录已经有序,时间复杂度是 O(n) 。最坏的情况当记录完全逆序的时候,n个记录要排序n-1趟,每一趟都要交换接近n次,这样最终的时间负责度O(n2) 。

 

对于时间复杂度我们认为最坏的情况是本算法的时间复杂度,所以冒泡排序的时间复杂度是O(n2)。

 

稳定性:有排序过程中,看到25和25*在排序前后的次序未改变,因此冒泡排序是稳定排序。

 

因s为在最坏情况下(即倒序),所有元素的比较次数总和为(0+1+…+n-1)→O(n2)。其他情况下也要考虑移动元素的次数。 故时间复杂度为O(n2)

 

五、插入排序

 

将待排序的记录Ri,插入到已排好序的记录表R1, R2 ,…., Ri-1中,得到一个新的、记录数增加1的有序表。 直到所有的记录都插入完为止。

 

设待排序的记录顺序存放在数组R[1…n]中,在排序的某一时刻,将记录序列分成两部分:

◆ R[1…i-1]:已排好序的有序部分;

◆ R[i…n]:未排好序的无序部分。

显然,在刚开始排序时,R[1]是已经排好序的。

 

1、插入排序法

例题: 关键字序列T=(13,6,3,31,9,27,5,11),其直接插入排序的排序过程如下:

【13】, 6, 3, 31, 9, 27, 5, 11

第1趟排序:   【6, 13】, 3, 31, 9, 27, 5, 11

第2趟排序:   【3, 6, 13】, 31, 9, 27, 5, 11

第3趟排序:   【3, 6, 13,31】, 9, 27, 5, 11

第4趟排序:   【3, 6, 9, 13,31】, 27, 5, 11

第5趟排序:   【3, 6, 9, 13,27, 31】, 5, 11

第6趟排序:   【3, 5, 6, 9, 13,27, 31】, 11

第7趟排序:   【3, 5, 6, 9, 11,13,27, 31】

大概意思就是,

第一趟:我们去认定第一个数13,然后用6和他对比,比13小,所以13后移,然后把6插在原先13所在位置,然后6和13就是已经排好序的。

第二趟:用3和【6,13】对比,比13小13往后移动,比6小6后移,吧3插在6原先的位置,现在【3,6,13】已经排好序了。

以此类推……

 

用python来实现:

结果:

【1,2,3,4,5】

 

2、插入排序复杂度分析

(1)   最好情况:若待排序记录按关键字从小到大排列(正序),算法中的内循环无须执行,则一趟排序时:关键字比较次数1次,每趟排序都要移动将近1个记录,这样n个记录最终的时间复杂度是O(n)。

(2)   最坏情况:若待排序记录按关键字从大到小排列(逆序),n个记录需要n-1趟排序,最坏的情况就是完全逆序的情况,每趟排序都要移动将近n个记录,这样最终的时间复杂度是O(n2)。

(3)   稳定性:稳定排序

 

 

六、选择排序

简单选择排序是常用的排序,学习交换排序理解交换排序理念,是对其他排序有力的补充。尤其学过交换排序之后,每趟排序都要进行频繁的交换,如何改进,使用选择排序,每趟只是记住位置,最后才交换,每趟最多交换一次。  

 

1、简单排序算法的思想

思想:选择最小的记录放在第一个位置,在剩余记录中选择最小的放在第二个位置,依次类推,直到所有记录有序。

 

2、简单选择排序算法:

例如:关键字序列T= (21,25,49,25*,16,08),其简单选择排序的具体实现过程如下:

原始序列: 21,25,49,25*,16,08

第1趟:08,25, 49,25*,16,21

第2趟:08,16, 49,25*,25,21

第3趟:08,16, 21,25*,25,49

第4趟:08,16, 21,25*,25,49

第5趟:08,16, 21,25*,25,49

解释一下:

第一趟:原始数列中挨个走一遍,最小的是8,然后把8和第一个数交换位置。

第二趟,第一个数已经是最小了,不用看。从第二个数开始挨个走一遍,最小的是16,把16和第二个数换位置。

以此类推……

6个数只需要5次就能排好。

 

用python来实现:

结果:

【1,2,3,4,5】

 

3、选择排序算法的时间复杂度分析

分析:

N个数排序,需要N-1趟排序,每一趟最坏的情况比较N-1次,因此最坏的情况就是接近N*N次比较。

 

结论:

选择排序的时间复杂度O(n2)

稳定性:不稳定排序,因为存在不相邻元素之间的交换(T= (21,25,49,25*,16,08)中的25和25*)

 

 

七、快速排序

 

快速排序,世界上公认的最快的排序方法,它每趟都能准确定位不止1个元素!当记录量很大的时候,而且杂乱无序时候,适合使用快速排序,因为每趟可以确定不止一个元素的位置,而且呈指数增加,所以特别快! 你一定想做一个效率高的的人,而不是只是完成任务而已。

所以学习快速排序,有很重要的意义,提高排序的速度,考虑算法的效率,做一个高效的程序员。

 

1、速排序思想

快速排序的思想:从待排序列中任取一个元素 (例如取第一个) 作为中心,所有比它小的元素一律前放,所有比它大的元素一律后放,形成左右两个子表;然后再对各子表重新选择中心元素并依此规则调整,直到每个子表的元素只剩一个。此时便为有序序列了。

 

2、速排序算法

我们知道了快速排序的思想,那么我们用一组数字直观的观察快速排序是如何进行工作的?

以关键字序列(256,301,751,129,937,863,742,694,076,438)为例,写出执行快速算法的各趟排序结束时,关键字序列的状态。

原始序列: 256  301  751  129  937  863  742  694  076  438

第一趟:   076  129  256  751  937  863  742  694  301  438

第二趟:   076  129  256  438  301  694  742  751  863  937

第三趟:   076  129  256  301  438  694  742  751  863  937

第四趟:   076  129  256  301  438  694  742  751  863  937

 

我们做这种题的思路是这样的:取第一个数作为中间数,然后看最后一个数,如果最后一个数大于中间数,不动看倒数第二个数。如果最后一个数,小于中间数,把这个数放在中间数本来的位置,然后回到开头,依次进行。

也就是,满足条件的保持不动,不满足条件的挪走后,再从列表另一头进行判断。

 

用python实现:

结果:

【1,2,3,4,5】
 

3、快速排序时间复杂度的分析

 

分析:设每个子表的支点都在中间(比较均衡),则:

第1趟比较,可以确定1个元素的位置;

第2趟比较(2个子表),可以再确定2个元素的位置;

第3趟比较(4个子表),可以再确定4个元素的位置;

第4趟比较(8个子表),可以再确定8个元素的位置;

         ……

只需log2n+1趟便可排好序。

 

而且,每趟需要比较和移动的元素也呈指数下降(最坏为n次),加上编程时使用了交替逼近技巧,更进一步减少了移动次数,所以速度特别快。

 

结论:

快速排序算法的时间复杂度:O(nlog2n)。

稳定性:不稳定排序,因为有不相邻元素之间的交换。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值