顶先最后推荐:哈哈,意思是放到顶部强调其重要性,但是应该我总结的六种算法看完了后再看的一篇醍醐灌顶的文章

一:冒泡排序(Bubble Sort)

  原理:假设有n个数,第一轮时:从第一个元素开始,与相邻的元素比较,如果前面的元素小就交换,直到第n-1个元素时,这样的结果是将最大的元素放到了最后,同理,第二轮还是从第一个元素开始比较,直到第n-2个元素,这样能够把剩下的n-1个数中的最大的数放到第n-1的位置,一直这样进行n-1轮就能够完成排序。

 def Bublesort(seq):
i = 0
j = 0
while i < len(seq):
while j < len(seq)-i-1:
if seq[j] > seq[j+1]:
seq[j],seq[j+1] = seq[j+1],seq[j]
else:
j+=1
j=0
i+=1 a=[3,4,6,2,1]
Bublesort(a)
print(a)

冒泡排序

  由代码可知,其时间复杂度为O(n2).

二:选择排序(Selection Sort)

  原理:选择排序的思路非常简单,每次都遍历找出上次剩下的元素中的最大数,然后和剩下数中随后一个元素交换位置,一个进行n-1次

 #coding:utf-8
#Attention:max标志需取为seq[0],我刚开始取了0,这会导致最后一次比较时出问题
def SelectionSort(seq):
i,j,maxel = 0,0,seq[0]
while i < len(seq):
while j < len(seq)-i:
if seq[j] > maxel:
maxel = j
j+=1
seq[maxel],seq[len(seq)-i-1] = seq[len(seq)-i-1],seq[maxel]
j,maxel=0,seq[0]
i+=1 a=[3,4,6,2,1]
SelectionSort(a)
print(a)

选择排序

  可以看出的是,其时间复杂度依然是O(n2),看起来和冒泡排序一样,但由于每轮其交换位置的次数少,故实际上其比冒泡排序好。

三:插入排序(Insertion Sort)

  原理:如下图所示,将第一个元素作为标准,每次将下一个元素放到前面正确的位置中去。

  技巧:从已排好序元素最后一个开始遍历比较,因为插入移动只会移动其后面的元素。

  

 def insertion_sort(a_list):
for index in range(1, len(a_list)):
current_value = a_list[index]
position = index
while position > 0 and a_list[position - 1] > current_value: #从目前元素开始向前,若>目前值就后移一位
a_list[position] = a_list[position - 1]
position = position - 1
a_list[position] = current_value a = [54, 26, 93, 17, 77, 31, 44, 55, 20]
insertion_sort(a)
print(a)

插入排序

  依旧可以看出的是,其时间复杂度为O(n2),但是他的不同之处在于其始终保持了一个部分有序的序列

四:希尔排序(Shell Sort)

  希尔排序这章书里面的配图不好,导致我理解错误直到运行程序出错才发现错误,后来看了些其他资料弄明白了。其实希尔排序就是跳跃式插入排序,我们试想一下,如果一个元素集是9,8,7,6,5,4,3,2,1,那么每次插入排序都要全部后移了,这样效率极低,如果能够不按顺序的进行插入排序就好多了,虽然每次并没有完全排好序,但是能够让他们离真实的位置更近,这就是其优势所在了。

  实现原理:每次取一个gap,第一次取集合元素个数整除2的结果,然后对从首元素开始每gap距离的元素组合成一个组并对其进行插入排序,假设集合[54, 26, 93, 17, 77, 31, 44, 55, 20],那么第一次gap为9//2=4,那么就能够有这些组:[54,77,20],[26,31],[93,44],[17,55],注意,并不是对其真的分组,只是将其看作一组后进行插入排序,那么结果是:[20, 26, 44, 17, 54, 31, 93, 55, 77],到此,第一次完成。第二次把gap改为上次gap//2的结果,也就是2,所以对上次的结果分组为[20,44,54,93,77],[26,17,31,55],对其进行插入排序后的结果是[20, 17, 44, 26, 54, 31, 77, 55, 93],到此第二次完成。第三次gap为1,注意,当gap为1时就表明是最后一轮了,最上此结果[20, 17, 44, 26, 54, 31, 77, 55, 93]全部进行插入排序就能够得到结果了。【仔细看看就能够发现其每次排序后真的是数字离其真实位置更近了】。

  注意:有个控制循环的条件就是每次分组的组数其实就是gap的值,容易看出是两层控制,外层控制进入的哪组分组,内层控制具体每组的插入排序

 def shell_sort(a_list):
sublist_count = len(a_list) // 2
while sublist_count > 0:
for start_position in range(sublist_count):
gap_insertion_sort(a_list, start_position, sublist_count)
print("After increments of size", sublist_count, "The list is",a_list)
sublist_count = sublist_count // 2 def gap_insertion_sort(a_list,start, gap):
for i in range(start + gap, len(a_list), gap):
current_value = a_list[i]
position = i
while position >= gap and a_list[position - gap] > current_value:
a_list[position] = a_list[position - gap]
position = position - gap
a_list[position] = current_value a_list = [54, 26, 93, 17, 77, 31, 44, 55, 20]
shell_sort(a_list)
print(a_list)

希尔排序

  

五:归并排序(Merge Sort)

  原理图:由图可以看出,其也是用了递归原理,base就是只剩一个元素时返回其本身

  

 def partition(seq, start, mid, stop):
lst = []
i = start
j = mid
while i < mid and j < stop:
if seq[i] < seq[j]:
lst.append(seq[i])
i+=1
else:
lst.append(seq[j])
j+=1
while i < mid:
lst.append(seq[i])
i+=1
while j < stop:
lst.append(seq[j])
j+=1
for i in range(len(lst)):
seq[start+i]=lst[i] def mergeSortRecursively(seq, start, stop):
if start >= stop-1:
return
mid = (start + stop) // 2
mergeSortRecursively(seq, start, mid)
mergeSortRecursively(seq, mid, stop)
partition(seq, start, mid, stop) a=[3,4,6,8,2,1,5,9]
mergeSortRecursively(a, 0, len(a))
print(a)

归并排序

  来分析下其时间复杂度吧,由于每次都将list二分,这是logn,而每次排列是n,由于这两小步组成一步,故时间复杂度为O(nlogn)

六:快速排序(Quick Sort)

  原理:如下,第一次以第一个元素为标志,将后面小的放他左边,大的放他右边,而后将其放到中间。第二次分别在其两边重复这样的过程,最后直到每组只有一个数据。

  

  有个需要注意的是最坏情况下为以排好序的集合,那么后面的数都标志大或者小,操作太多或者无效,最理想的是标志能够是平均值左右,故最好对数据进行随机化处理。

  还有,看完代码后注意比较,可以是快速排序与归并排序是某种程度相反的,归并到了最后两个元素才开始排序,从部分有序积累到全部有序,而二分是反的,从第一次二分就是整个数列的二分,,最后二分到只有两个元素时,此时完成了全部有序。

 import random
def partition(seq, start, stop):
pivotIndex = start
pivot = seq[pivotIndex]
i = start+1
j = stop-1
while i <= j:
while pivot > seq[i]:
i+=1
while pivot < seq[j]:
j-=1
if i < j:
seq[j],seq[i] = seq[i],seq[j]
i+=1
j-=1
seq[pivotIndex],seq[j] = seq[j],pivot
return j def quicksortRecursively(seq, start, stop):
if start >= stop-1:
return
pivotIndex = partition(seq, start, stop)
quicksortRecursively(seq, start, pivotIndex)
quicksortRecursively(seq, pivotIndex+1, stop) def quicksort(seq):
# randomize the sequence first
for i in range(len(seq)):
j = random.randint(0,len(seq)-1)
seq[i],seq[j] = seq[j],seq[i] quicksortRecursively(seq, 0, len(seq)) a=[3,4,6,8,2,1,5,9]
quicksort(a)
print(a)

快速排序

  同理可以分析出其时间复杂度为O(nlogn)

python 下的数据结构与算法---6:6大排序算法的更多相关文章

  1. 数据结构和算法(Golang实现)(25)排序算法-快速排序

    快速排序 快速排序是一种分治策略的排序算法,是由英国计算机科学家Tony Hoare发明的, 该算法被发布在1961年的Communications of the ACM 国际计算机学会月刊. 注:A ...

  2. 数据结构和算法(Golang实现)(18)排序算法-前言

    排序算法 人类的发展中,我们学会了计数,比如知道小明今天打猎的兔子的数量是多少.另外一方面,我们也需要判断,今天哪个人打猎打得多,我们需要比较. 所以,排序这个很自然的需求就出来了.比如小明打了5只兔 ...

  3. 数据结构和算法(Golang实现)(19)排序算法-冒泡排序

    冒泡排序 冒泡排序是大多数人学的第一种排序算法,在面试中,也是问的最多的一种,有时候还要求手写排序代码,因为比较简单. 冒泡排序属于交换类的排序算法. 一.算法介绍 现在有一堆乱序的数,比如:5 9 ...

  4. 数据结构和算法(Golang实现)(21)排序算法-插入排序

    插入排序 插入排序,一般我们指的是简单插入排序,也可以叫直接插入排序.就是说,每次把一个数插到已经排好序的数列里面形成新的排好序的数列,以此反复. 插入排序属于插入类排序算法. 除了我以外,有些人打扑 ...

  5. 数据结构和算法(Golang实现)(22)排序算法-希尔排序

    希尔排序 1959 年一个叫Donald L. Shell (March 1, 1924 – November 2, 2015)的美国人在Communications of the ACM 国际计算机 ...

  6. 数据结构和算法(Golang实现)(23)排序算法-归并排序

    归并排序 归并排序是一种分治策略的排序算法.它是一种比较特殊的排序算法,通过递归地先使每个子序列有序,再将两个有序的序列进行合并成一个有序的序列. 归并排序首先由著名的现代计算机之父John_von_ ...

  7. 数据结构和算法(Golang实现)(24)排序算法-优先队列及堆排序

    优先队列及堆排序 堆排序(Heap Sort)由威尔士-加拿大计算机科学家J. W. J. Williams在1964年发明,它利用了二叉堆(A binary heap)的性质实现了排序,并证明了二叉 ...

  8. 一篇夯实一个知识点系列--python实现十大排序算法

    写在前面 排序是查找是算法中最重要的两个概念,我们大多数情况下都在进行查找和排序.科学家们穷尽努力,想使得排序和查找能够更加快速.本篇文章用Python实现十大排序算法. 干货儿 排序算法从不同维度可 ...

  9. 数据结构和算法(Golang实现)(20)排序算法-选择排序

    选择排序 选择排序,一般我们指的是简单选择排序,也可以叫直接选择排序,它不像冒泡排序一样相邻地交换元素,而是通过选择最小的元素,每轮迭代只需交换一次.虽然交换次数比冒泡少很多,但效率和冒泡排序一样的糟 ...

  10. 十大排序算法总结(Python3实现)

    十大排序算法总结(Python3实现) 本文链接:https://blog.csdn.net/aiya_aiya_/article/details/79846380 目录 一.概述 二.算法简介及代码 ...

随机推荐

  1. [Git]Git远程仓库

    1.创建ssh key 查看主目录下面 C:\Users\Administrator\.ssh 是否存在 id_rsa 和 id_rsa.pub 文件,如果不存在需要generate new key. ...

  2. JS冒泡事件与处理

    JavaSciprt事件中有两个很重要的特性:事件冒泡以及目标元素. 事件冒泡: 当一个元素上的事件被触发的时候,比如说鼠标点击了一个按钮,同样的事件将会在那个元素的所有祖先元素中被触发.这 一过程被 ...

  3. CLR via C#可空值类型

    我们知道,一个值类型的变量永远不可能为null.它总是包含值类型本身.遗憾的是,这在某些情况下会成为问题.例如,设计一个数据库时,可将一个列定义成为一个32位的整数,并映射到FCL的Int32数据类型 ...

  4. spring注解机制和XML配置机制之间的比较

    XML配置的优缺点: 优点有:1. XML配置方式进一步降低了耦合,使得应用更加容易扩展,即使对配置文件进一步修改也不需要工程进行修改和重新编译.2. 在处理大的业务量的时候,用XML配置应该更加好一 ...

  5. log4j.propertise配置文件

    # level : 是日志记录的优先级,分为OFF.FATAL.ERROR.WARN.INFO.DEBUG.ALL或者您定义的级别.Log4j建议只使用四个级别,优先级从高到低分别是ERROR.WAR ...

  6. HTTP分块传输

    HTTP分块传输 用途 对于在发送HTTP头部前,无法计算出Content-Length的HTTP请求及回复(例如WEB服务端产生的动态内容),可以使用分块传输,使得不至于等待所有数据产生后,再发送带 ...

  7. select m objects from n objects randomly

    Q: how to select m objects randomly from n objects with euqal possibility? A: allocate an array of m ...

  8. webkit的基本应用

    新建Qt Widgets Application->Browser01 修改.pro文件内容: #------------------------------------------------ ...

  9. Keil增量编译build异常

    装完MDK4.6/4.7a,发现没有修改源文件的情况下,单击build,每次都是重新编译,之前测试过重新建立工程/装回4.22,解决了该问题,当时并没多想原因.这次又出现了这个问题,重装了很久,也都这 ...

  10. 对WM_NCHITTEST消息的了解+代码实例进行演示(消息产生消息,共24个枚举值)

    这个消息比较实用也很关键,它代表非显示区域命中测试.这个消息优先于所有其他的显示区域和非显示区域鼠标消息.其中lParam参数含有鼠标位置的x和y屏幕坐标,wParam 这里没有用. Windows应 ...