排序算法总结

直接插入排序

直接插入排序是一种简单的插入排序法,其基本思想是:把待排序的纪录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的纪录插入完为止,得到一个新的有序序列。

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


希尔排序(shell sort)

希尔排序的实质就是分组插入排序,该方法又称缩小增量排序,因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)

上面代码逻辑没问题,最终可以排序好,但问题是python不是传址嘛,里面的list类型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  


简单选择排序的改进——二元选择排序


简单选择排序,每趟循环只能确定一个元素排序后的定位。我们可以考虑改进为每趟循环确定两个元素(当前趟最大和最小记录)的位置,从而减少排序所需的循环次数。改进后对n个数据进行排序,最多只需进行[n/2]趟循环即可。


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


交换排序—冒泡排序(Bubble Sort)

基本思想:
在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。


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

快速排序 (quick sort)

快速排序(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



归并排序(merge sort)

该算法是采用分治法(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


你可能感兴趣的:(排序算法)