算法导论 第二部分——排序和顺序统计量
2016-07-07 15:18
302 查看
一、堆排序 : 原址排序 复杂度: nlg n
最大堆: A[parent(i)] > = A[i]
最小堆: A[parent(i)] < = A[i]
除了最底层外,其它层都是满状态。
判断节点是否为叶节点: [n/2]+1,.....n 均为叶节点
二、快速排序 原址
最坏时间复杂度: n^2 ,但是是实际应用中最好的排序算法,期望时间复杂度:nlgn,而且隐藏的因子特别小。
performance:
worst situation:
T(n) = T(n-1) + k; 它的复杂度为 n^2 ,当数组已经是排好序的,那么他需要进行 n^2 次运算
best situation:
T(n) = 2T(n/2)+k; 当两个子问题的规模都不大于n/2,这时候快速排序的性能最好 nlg n次运算
平衡的划分:
只要每次划分是一种常数比例的划分,都会产生深度为lgn的递归树
例如: T(n) = T(n/10)+T(9n/10) + k;
quicksort using random function
三、线性时间排序
1、 决策树模型:
每次比较判断可以影响下一次的比较,
定理:对于一个比较排序算法在最坏情况下,都需要做Ω(nlgn)次比较。
参考: http://www.cnblogs.com/Anker/archive/2013/01/25/2876397.html
2、计数排序 : 时间复杂度为n ,其实是max-min+1,需要额外开辟内存空间
前提条件: 所有的元素都必须在一个范围内,如: min<a[i]<=max
四:中位数和顺序统计量
1、期望为线性时间的选择算法: 最坏时间为n^2
c++代码:
View Code
最大堆: A[parent(i)] > = A[i]
最小堆: A[parent(i)] < = A[i]
除了最底层外,其它层都是满状态。
判断节点是否为叶节点: [n/2]+1,.....n 均为叶节点
//Max-heapify(A,i) : A为一个 假定 left(i) right(i)的二叉树都是最大堆 。 但是A[i]可能小于孩子 。 时间复杂度为: o(h) //build_max_heap(A,len) : 将一个数组转换为 最大堆(从底向上的建堆) , 时间复杂度为: o(n) //heap_sort(A,len) : 将 A 进行排序 复杂度 为 nlg(n) void max_heapify(int *A , int i,int len) { int r = RIGHT(i); int l = LEFT(i); int large = i; if (i <= len&&*(A + i-1) < *(A+r-1)) large = r; if (i <= len && *(A+large-1)<*(A+l-1)) large = l; if (large == i) return; else swap(A, large-1, i-1,len); if (i <= len && 2 * i < len/2+1) // decide if the left son node is leaf node max_heapify(A, large, len); // not leaf node , carry on the recursion else return; // end the recursion } void build_max_heap(int *A, int len) { for (int i = len / 2; i>0; i--) max_heapify(A,i,len); } void heap_sort(int *A, int len) { build_max_heap(A,len); for (int i = len; i > 0; i--) { swap(A, i - 1, 0 ,len); max_heapify(A,1,i); } }
二、快速排序 原址
最坏时间复杂度: n^2 ,但是是实际应用中最好的排序算法,期望时间复杂度:nlgn,而且隐藏的因子特别小。
// partition(); 将数组A[p,……,r] 分成 A[p,….,q-1]<=A[q]<=A[q+1,r],返回q的数组下标 // quick_sort() : 递归调用,将分割好的数组继续分割 int PARTITION(int *A ,int p , int r ,int len) { if (p >= len || r >= len|| p<0||r<=0) { cout << "function PARTITION erro : the p or r is out range of the vector or array" << endl; return 0; } int i = p - 1; int x = 0; for (int j = p; j < r; j++) { if (*(A+j)<*(A+r)) { i = i + 1; EXCHANGE(A,i,j,len); } } EXCHANGE(A,r,i+1,len); return i + 1; } void QUICK_SORT(int *A,int p,int r,int len) { if (p >= r) { cout << "function QUICK_SORT error : r must larger than p" << endl; return; } if (p >= len || r >= len||p<0||r<=0) { cout << "function QUICK_SORT error : the p or r is out range of the vector or array" << endl; return; } if (p == r) { cout << "end of calling of QUICK_SORT" << endl; return; } int mid=PARTITION(A,p,r,len); cout << "mid is :" << mid << " p ="<<p<<" r="<<r<<" len="<<len<<endl; QUICK_SORT(A,p,mid-1,len); QUICK_SORT(A,mid+1,r,len); output(A,len); }
performance:
worst situation:
T(n) = T(n-1) + k; 它的复杂度为 n^2 ,当数组已经是排好序的,那么他需要进行 n^2 次运算
best situation:
T(n) = 2T(n/2)+k; 当两个子问题的规模都不大于n/2,这时候快速排序的性能最好 nlg n次运算
平衡的划分:
只要每次划分是一种常数比例的划分,都会产生深度为lgn的递归树
例如: T(n) = T(n/10)+T(9n/10) + k;
quicksort using random function
RANDOMIZED-PARTITION(A, p, r): i = RANDOM(p, r ) exchange A[r ] ↔ A[i ] return PARTITION(A, p, r )
三、线性时间排序
1、 决策树模型:
每次比较判断可以影响下一次的比较,
定理:对于一个比较排序算法在最坏情况下,都需要做Ω(nlgn)次比较。
参考: http://www.cnblogs.com/Anker/archive/2013/01/25/2876397.html
2、计数排序 : 时间复杂度为n ,其实是max-min+1,需要额外开辟内存空间
前提条件: 所有的元素都必须在一个范围内,如: min<a[i]<=max
int * count_sort(int *a ,int n){ //initialize int max=0xffffffff, min=0x7fffffff; for (int i = 0; i < n; i++){ if (*(a + i)>max) max = *(a+i); if (*(a + i) < min) min = *(a + i); } const int len = max - min+1; int *c = new int[len]; int *re = new int ; memset(c,0,len*4); //count the number of every element in a[] then store in c[] for (int i = 0; i < n; i++){ *(c + *(a+i) - min) += 1; } //sort based c[] for (int i = 0,j=0; i < len; i++){ int k = 0; while (k < *(c + i)){ *(re + j) = min + i; j++; k++; } } delete []c; return re; }
四:中位数和顺序统计量
1、期望为线性时间的选择算法: 最坏时间为n^2
RANDOMIZED_SELECT(A,p,r,i) if p==r then return A[p] //通过partition函数产生q值,与快速排序的partition原理相同 q = RANDOMIZED_PARTITION(A,p,r) k = q-p+1; if i==k then return A[q] else if i<k then return RANDOMIZED_SELECT(A,p,q-1,i) else return RANDOMIZED_SELECT(A,p,q-1,i-k)
c++代码:
#include <stdio.h> #include <stdlib.h> int partition(int* datas,int beg,int last,int mid); int select(int* datas,int length,int i); void swap(int* a,int *b); int main() { int datas[12]={32,23,12,67,45,78,10,39,9,58,125,84}; int i,ret; printf("The array is: \n"); for(i=0;i<12;++i) printf("%d ",datas[i]); printf("\n"); for(i=1;i<=12;++i) { ret=select(datas,12,i); printf("The %dth least number is: %d \n",i,datas[i-1]); } exit(0); } int partition(int* datas,int beg,int last,int mid) { int i,j; swap(datas+mid,datas+last); i=beg; for(j=beg;j<last;j++) { if(datas[j] < datas[last]) { swap(datas+i,datas+j); i++; } } swap(datas+i,datas+last); return i; } int select(int* datas,int length,int i) { int groups,pivot; int j,k,t,q,beg,glen; int mid; int temp,index; int *pmid; if(length == 1) return datas[length-1]; if(length % 5 == 0) groups = length/5; else groups = length/5 +1; pmid = (int*)malloc(sizeof(int)*groups); index = 0; for(j=0;j<groups;j++) { beg = j*5; glen = beg+5; for(t=beg+1;t<glen && t<length;t++) { temp = datas[t]; for(q=t-1;q>=beg && datas[q] > datas[q+1];q--) swap(datas+q,datas+q+1); swap(datas+q+1,&temp); } glen = glen < length ? glen : length; pmid[index++] = beg+(glen-beg)/2; } for(t=1;t<groups;t++) { temp = pmid[t]; for(q=t-1;q>=0 && datas[pmid[q]] > datas[pmid[q+1]];q--) swap(pmid+q,pmid+q+1); swap(pmid+q+1,&temp); } //printf("mid indx = %d,mid value=%d\n",pmid[groups/2],datas[pmid[groups/2]]); mid = pmid[groups/2]; pivot = partition(datas,0,length-1,mid); //printf("pivot=%d,value=%d\n",pivot,datas[pivot]); k = pivot+1; if(k == i) return datas[pivot]; else if(k < i) return select(datas+k,length-k,i-k); else return select(datas,pivot,i); } void swap(int* a,int *b) { int temp = *a; *a = *b; *b = temp; }
View Code
相关文章推荐
- Java static 的一两点使用
- 242. Valid Anagram
- VS中的快捷键快速格式化代码,使好看,整齐
- vi/vim命令大全
- maven 系统找不到指定的路径
- Caffe学习系列(12):训练和测试自己的图片
- thinkphp 模板截取中文字符串函数
- 我的Android进阶之旅------>解决Error:Could not find property 'compile' on org.gradle.api.internal.artifacts.
- struts2 小结
- How To Restart The Concurrent Manager In Unix
- ios developer tiny share-20160707
- ios developer tiny share-20160707
- Vmware不能玩游戏的解决方法
- 计算当前时间的到晚上00:00:00的相差时间
- dotnetCore系列:使用Visual Studio code 创建DotNet Core 1.0应用并调试(1)
- 批处理执行Testng
- Integer比较值的时候小心使用
- 进程间通信(三)—信号量
- iOS设计模式(七) 迭代器模式
- A^B约数之和