您的位置:首页 > 其它

各种排序算法分析比较

2014-04-20 17:51 155 查看
先研究典型的吧,归并与快排。

遇到一个问题,要求利用常数阶的空间、在时间复杂度为O(NLogN)的情况下为一个单链表排序。

回忆:时间复杂度为O(NLogN)的排序算法有:快速排序、归并排序、堆排序,它们的空间复杂度O(1) 、O(N) 、O(N) 。(快排不稳定,归并稳定,堆排序不稳定)

            其中快排最坏的情况下,时间复杂度为O(N^2),显然某些测试用例下不满足O(NLogN)。而考虑归并排序,空间复杂度之所以不满足,在在数组的合并排序操作,需要额外的O(N)辅助空间;但是若是在单链表中进行两个有序数列的合并,并不需要额外的空间,使用指针操作即可。因此,这里选择归并比较合适。对排序空间复杂度不满足。

==============================================================================================================================

分治法:将规模较大的问题,分解为若干个与原问题性质相同的子问题;求解子问题;并将子问题的解合并,得到最后的解。

由此可见分治法的一般步骤:分解、求解、合并。由于子问题与原问题性质相同,采用递归是较为简单的方法。

==============================================================================================================================

归并排序

模板预览:

void DaC(int *a, int p, int q) {
if(p == q) return;//最小有序序列

m = divide(p, q);//分解问题
DaC(a, p, m);
DaC(a, m + 1, q);
merge(vt, p, m, q);//合并

}

解释:将数组A[p, q]平分问两部分A[p, m]  A[m+1, q], 分别求解这两个子数组使它们们有序,最后将它们合并成有序序列。

            其中两个子数组序列会被分为更小的子序列,直到只剩下一个数据,代表排成了有序序列。

代码:

class Solution{
public:
void MergeSort(vector<int> &vt){
sort(vt, 0, vt.size() - 1);
}

void sort(vector<int> &vt, int p, int q) {
if(q == p) return;

int m = (p + q) / 2;//divide(p, q);
sort(vt, p, m);
sort(vt, m + 1, q);
merge(vt, p, m, q);
}

void merge(vector<int> &vt, int p, int m, int q) {

vector<int> vtmp(q-p+1, 0);

int i = p;
int j = m + 1;

int n = 0;
while(i <= m && j <= q) {
if(vt[i] <= vt[j]) {
vtmp[n++] = vt[i++];
} else {
vtmp[n++] = vt[j++];
}
}
while(i <= m) {
vtmp[n++] = vt[i++];
}

while(j <= q) {
vtmp[n++] = vt[j++];
}
for(n = 0; n < q-p+1; n++) {
vt[n + p] = vtmp
;
}
}

void swap(int &a, int &b) {
int tmp;
tmp = a;
a = b;
b = tmp;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: