直接插入排序是一种简单的插入排序法,其基本思想是:把待排序的纪录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的纪录插入完为止,得到一个新的有序序列。
def insert_sort(li): for i in range(len(li)-1): tocomp=li[i+1] for j in range(i+1): if tocomp<li[i-j]: li[i-j+1]=li[i-j] li[i-j]=tocomp else: #print li break li=[79,66,43,83,72,87,38,55,91,30,49,9,100,45,76,32,77,87] insert_sort(li) print li
希尔排序的实质就是分组插入排序,该方法又称缩小增量排序,因DL.Shell于1959年提出而得名。
该方法的基本思想是:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率上比前两种方法有较大提高。
以n=10的一个数组49, 38, 65, 97, 26, 13, 27, 49, 55, 4为例
第一次 gap = 10 / 2 = 5
49 38 65 97 26 13 27 49 55 4
1A 1B
2A 2B
3A 3B
4A 4B
5A 5B
1A,1B,2A,2B等为分组标记,数字相同的表示在同一组,大写字母表示是该组的第几个元素, 每次对同一组的数据进行直接插入排序。即分成了五组(49, 13) (38, 27) (65, 49) (97, 55) (26, 4)这样每组排序后就变成了(13, 49) (27, 38) (49, 65) (55, 97) (4, 26),下同。
第二次 gap = 5 / 2 = 2
排序后
13 27 49 55 4 49 38 65 97 26
1A 1B 1C 1D 1E
2A 2B 2C 2D 2E
第三次 gap = 2 / 2 = 1
4 26 13 27 38 49 49 55 97 65
1A 1B 1C 1D 1E 1F 1G 1H 1I 1J
第四次 gap = 1 / 2 = 0 排序完成得到数组:
4 13 26 27 38 49 49 55 65 97
def insert_sort(l): for i in range(len(l)-1): tocomp=l[i+1] for j in range(i+1): if tocomp<l[i-j]: l[i-j+1]=l[i-j] l[i-j]=tocomp else: break return l def shell_sort(li): d=len(li)/2 while d>0: li1=li li=[] k=0 while len(li1)!=len(li): li.extend(insert_sort(li1[k::d])) k+=1 #print li d/=2 print li print id(li) l=[79,66,43,83,72,87,38,55,91,30,49,9,100,45,76,32,77,87] shell_sort(l) print l print id(l)
基本思想:
在要排序的一组数中,选出最小(或者最大)的一个数与第1个位置的数交换;然后在剩下的数当中再找最小(或者最大)的与第2个位置的数交换,依次类推,直到第n-1个元素(倒数第二个数)和第n个元素(最后一个数)比较为止。
li=[3,5,1,3,6,9,2,3,8,0,8,6] def selection_sort(li): for i in range(len(li)): minnum=li[i] index=i for j in range(len(li)-i): if li[i+j]<minnum: minnum=li[i+j] index=j+i li[index]=li[i] li[i]=minnum selection_sort(li) print li
li=[3,5,1,3,6,9,2,3,8,0,8,6] def selection_sort(li): for i in range(len(li)/2): minnum=li[i] maxnum=li[i] index1=i index2=i for j in range(len(li)-2*i): if li[i+j]<minnum: minnum=li[i+j] index1=j+i if li[i+j]>maxnum: maxnum=li[i+j] index2=i+j li[index1]=li[i] li[i]=minnum li[index2]=li[len(li)-1-i] li[len(li)-1-i]=maxnum #print li selection_sort(li) print li
li=[3,5,1,3,6,9,2,3,8,0,8,6] def bubble_sort(li): for i in range(len(li)-1): for j in range(len(li)-1-i): if li[j]>li[j+1]: tmp=li[j] li[j]=li[j+1] li[j+1]=tmp print li bubble_sort(li) print li
快速排序(Quicksort)是对冒泡排序的一种改进。
一趟快速排序的算法是:
1)设置两个变量i、j,排序开始的时候:i=0,j=N-1;
2)以第一个数组元素作为关键数据,赋值给key,即key=A[0];
3)从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]和A[i]互换;
4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]互换;
5)重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。
li=[3,5,1,3,6,9,2,3,8,0,8,6] def qs(li,si,ei): if ei-si>0: ls=[] lg=[] tocomp=li[si] for i in range(ei-si): if li[si+i+1]<=li[si]: ls.append(li[si+i+1]) else: lg.append(li[si+i+1]) for i in range( len(ls)): li[si+i]=ls[i] li[si+len(ls)]=tocomp for i in range(len(lg)): li[si+len(ls)+1+i]=lg[i] qs(li,si,si+len(ls)-1) qs(li,ei-len(lg)+1,ei) def quick_sort(li): qs(li,0,len(li)-1) quick_sort(li) print li
该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
归并过程为:比较a[i]和a[j]的大小,若a[i]≤a[j],则将第一个有序表中的元素a[i]复制到r[k]中,并令i和k分别加上1;否则将第二个有序表中的元素a[j]复制到r[k]中,并令j和k分别加上1,如此循环下去,直到其中一个有序表取完,然后再将另一个有序表中剩余的元素复制到r中从下标k到下标t的单元。归并排序的算法我们通常用递归实现,先把待排序区间[s,t]以中点二分,接着把左边子区间排序,再把右边子区间排序,最后把左区间和右区间用一次归并操作合并成有序的区间[s,t]。
li=[3,5,1,3,6,9,2,3,8,0,8,6] def ms(li,s1,e1,s2,e2): ls=[] i1=s1 i2=s2 while i1<=e1 and i2<=e2: if li[i1]<li[i2]: ls.append(li[i1]) i1+=1 else: ls.append(li[i2]) i2+=1 if i1>e1: ls.extend(li[i2:e2+1]) else: ls.extend(li[i1:e1+1]) for i in range(len(ls)): li[i+s1]=ls[i] def merge_sort(li): k=1 while k<len(li): s1=0 e2=min(len(li)-1,2*k-1) while 1 and s1+k-1<len(li)-1: ms(li,s1,s1+k-1,s1+k,e2) s1=e2+1 e2=min(len(li)-1,e2+2*k) if s1>=len(li)-1: break #print li k*=2 merge_sort(li) print li
堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。
主要是建堆与堆调整,具体参见我之前的博客数据结构堆的实现。
def heap_adjust(li,exch,bar): flag=1 while flag==1: flag=0 ch=-1 if 2*exch<=bar: if 2*exch+1<=bar: if min(li[2*exch-1],li[2*exch])<li[exch-1]: flag=1 if min(li[2*exch-1],li[2*exch])==li[2*exch-1]: ch=2*exch else: ch=2*exch+1 else: if li[2*exch-1]<li[exch-1]: flag=1 ch=2*exch if ch>=0: tmp=li[ch-1] li[ch-1]=li[exch-1] li[exch-1]=tmp exch=ch def heapfy(li): parent=len(li)/2 while parent>=1: exch=-1 child1=2*parent child2=2*parent+1 if child2<=len(li): if min(li[child1-1],li[child2-1])<li[parent-1]: if min(li[child1-1],li[child2-1])==li[child1-1]: exch=child1 else: exch=child2 else: if li[child1-1]<li[parent-1]: exch=child1 if exch>0: tmp=li[exch-1] li[exch-1]=li[parent-1] li[parent-1]=tmp heap_adjust(li,exch,len(li)) parent-=1 def heap_sort(li): heapfy(li) for i in range(len(li)): tmp=li[0] li[0]=li[len(li)-1-i] li[len(li)-1-i]=tmp heap_adjust(li,1,len(li)-i-1) #print li li=[79,66,43,83,72,87,38,55,91,30,49,9] heap_sort(li) print li