排序算法总结
来源:互联网 发布:大连理工软件学院几本 编辑:程序博客网 时间:2024/05/22 05:08
直接插入排序
直接插入排序是一种简单的插入排序法,其基本思想是:把待排序的纪录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的纪录插入完为止,得到一个新的有序序列。
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 breakli=[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 ldef 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 lprint 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]=minnumselection_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 liselection_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 libubble_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*=2merge_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=chdef 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-=1def 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 lili=[79,66,43,83,72,87,38,55,91,30,49,9]heap_sort(li) print li
桶排序
- #include "stdafx.h"
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- extern void quick_sort(int a[], int p, int q);/* not necessary */
- struct barrel {
- int node[10];
- int count;/* the num of node */
- };
- void bucket_sort(int data[], int size)
- {
- int max, min, num, pos;
- int i, j, k;
- struct barrel *pBarrel;
- max = min = data[0];
- for (i = 1; i < size; i++) {
- if (data[i] > max) {
- max = data[i];
- }
- else if (data[i] < min) {
- min = data[i];
- }
- }
- num = (max - min + 1) / 10 + 1;
- pBarrel = (struct barrel*)malloc(sizeof(struct barrel) * num);
- memset(pBarrel, 0, sizeof(struct barrel) * num);
- /* put data[i] into barrel which it belong to */
- for (i = 0; i < size; i++) {
- k = (data[i] - min + 1) / 10;/* calculate the index of data[i] in barrel */
- (pBarrel + k)->node[(pBarrel + k)->count] = data[i];
- (pBarrel + k)->count++;
- }
- pos = 0;
- for (i = 0; i < num; i++) {
- quick_sort((pBarrel + i)->node, 0, (pBarrel + i)->count);/* sort node in every barrel */
- for (j = 0; j < (pBarrel + i)->count; j++) {
- data[pos++] = (pBarrel + i)->node[j];
- }
- }
- free(pBarrel);
- }
- void main()
- {
- int data[] = { 78, 17, 39, 26, 72, 94, 21, 12, 23, 91 }, i;
- int size = sizeof(data) / sizeof(int);
- bucket_sort(data, size);
- for (i = 0; i < size; i++)
- printf("%d ", data[i]);
- }
【源码】常用排序算法汇总(实现+优化)
- 算法--排序算法总结
- 算法:排序算法总结
- 算法:排序算法总结
- 算法-排序算法总结
- 算法-排序算法总结
- 【排序算法】排序算法总结
- 排序算法总结---希尔排序
- 排序算法总结---冒泡排序
- 排序算法总结----快速排序
- 排序算法总结---希尔排序
- 排序算法总结【内排序】
- 排序算法之内排序总结
- 排序算法总结:冒泡排序
- 【排序算法总结】冒泡排序
- 【排序算法总结】选择排序
- 排序算法总结
- 排序算法大总结
- 排序算法总结
- Qt 16进制字符串跟QByteArray互转
- java数据类型划分
- 1042 - Secret Origins
- centos 安装php
- SAM数据格式学习3之官方文档
- 排序算法总结
- 面向对象的设计原则(一)
- POJ 1206 置换群
- Hdu 3068 最长回文【manacher算法】
- 关联容器Map c++ stl
- svn commit
- edittext获取焦点并弹出软键盘
- CodeForces - 582B Once Again... (LIS变型)好题
- 【bzoj2145】悄悄话 乱搞