数据结构---------快速排序
2017-03-03 08:34
127 查看
我们首先来回忆一下快速排序有哪些知识,以下是我看完书几天后还剩下的东西:
特点:快速排序快,好,相对于其他排序首选快速排序(至于为什么,记不得了。。)
分析:时间复杂度O(NlogN),最坏情况O(N2)
思想:找到一个枢纽元素,小于枢纽元素的在左面,大于枢纽元素的在右面
实现:递归的实现,先找到枢纽元后,递归的在其左右两个集合中找到枢纽元,至于递归的出口。。记不得了
接下来就补充一下自己记不牢的知识点吧:
1.介绍:快速排序(quitsort)是在实践中最快的已知排序算法,它的平均运行时间时O(N*logN),该算法之所以特别快,主要是由于非常精炼的高度优化的内部循环。它的最坏情形的性能为O(N2)。
2.实现步骤:
如果S中元素的个数是0或1,则返回。
选取S中任一元素v,称之为枢纽元(pivot)。
将S-{v}分成两个不相交的集合,S1={x<=v},S2={x>=v}。
返回quitsort(S1)后v被放在了正确的位置,继而返回quiksort(S2)。
3.注意几点:
选取枢纽元有多重方法,我们采用前中后三个数中间数法。
如果排序的过程中i和j遇到与pivot相同的元素,那么我们就让i和j都停止,进行交换,因为进行不必要的交换建立的两个均衡的子数组要比冒险的到两个不均衡的子数组要好。
对于很小的数组(N<=20),快速排序不如插入排序好。
以下是代码实现:
直接插入排序:
void InsertionSort(ElementType A[], int N)
{
int j, P;
ElementType tmp;
for (P = 1; P < N; P++)
{
tmp = A[P];
for (j = P; j > 0 && A[j - 1] > tmp; j--)//若条件已满足,此时j的值已减一
A[j] = A[j - 1];
A[j] = tmp;
}
}
对于快速排序的分析:
最坏情况:枢纽元素每次都是第一个,则时间复杂度为O(N2)。
最好情况:枢纽元素每次都是中间,则时间复杂度为O(N*logN)。
平均情况:O(N*logN)
排序的一般下界:任何只用到比较的算法在最坏情况下需要Ω(N*logN)次比较,因此归并排序和堆排序在一个常数因子范围内是最优的,进一步,证明在平均情况下,快速排序在相差一个常数因子的范围内平均最优的。
特点:快速排序快,好,相对于其他排序首选快速排序(至于为什么,记不得了。。)
分析:时间复杂度O(NlogN),最坏情况O(N2)
思想:找到一个枢纽元素,小于枢纽元素的在左面,大于枢纽元素的在右面
实现:递归的实现,先找到枢纽元后,递归的在其左右两个集合中找到枢纽元,至于递归的出口。。记不得了
接下来就补充一下自己记不牢的知识点吧:
1.介绍:快速排序(quitsort)是在实践中最快的已知排序算法,它的平均运行时间时O(N*logN),该算法之所以特别快,主要是由于非常精炼的高度优化的内部循环。它的最坏情形的性能为O(N2)。
2.实现步骤:
如果S中元素的个数是0或1,则返回。
选取S中任一元素v,称之为枢纽元(pivot)。
将S-{v}分成两个不相交的集合,S1={x<=v},S2={x>=v}。
返回quitsort(S1)后v被放在了正确的位置,继而返回quiksort(S2)。
3.注意几点:
选取枢纽元有多重方法,我们采用前中后三个数中间数法。
如果排序的过程中i和j遇到与pivot相同的元素,那么我们就让i和j都停止,进行交换,因为进行不必要的交换建立的两个均衡的子数组要比冒险的到两个不均衡的子数组要好。
对于很小的数组(N<=20),快速排序不如插入排序好。
以下是代码实现:
/* * 交换元素· */ void Swap(int *a, int *b) { int temp; temp = *a; *a = *b; *b = temp; } /* 返回枢纽元素 */ ElementType Median(ElementType A[], int Left, int Right) { int Center = (Left + Right) / 2; if (A[Left] > A[Center]) Swap(&A[Left], &A[Center]); if (A[Left] > A[Right]) Swap(&A[Left], &A[Right]); if (A[Center] > A[Right]) Swap(&A[Left], &A[Right]); Swap(&A[Center], &A[Right]); return A[Right]; } /* 快速排序 */ void Qsort(ElementType A[], int Left, int Right) { int i, j; ElementType pivot; //之前此处如果没有if判断,导致程序崩溃无法运行, //因为递归的程序没有出口,无限循环调用自己。 if (Left + Cutoff >= Right) { //当要排序的数据个数多余3个时使用快速排序 //外层循环直至i<j时,跳出循环,交换i位置元素与枢纽元素 //否则,比i位置大的元素与比j位置小的元素进行交换 pivot = Median(A, Left, Right); i = Left; j = Right - 1; for (; ; ) { while (A[++i] < pivot) {} while (A[++j] > pivot) {} if (i < j) Swap(&A[i], &A[j]); else break; } Swap(&A[i], &A[Right - 1]); //递归的对比枢纽元素小和比枢纽元素大数据进行快速排序 Qsort(A, Left, i - 1); Qsort(A, i + 1, Right); } else //当要排序的数据个数多余3个时使用直接插入排序,效率高于快速排序 InsertionSort(A + Left, Right - Left + 1); } int main() { int b[10]; int i; int a[10] = { 2, 4, 67, 12, 43, 78, 5, 3, 8, 87}; Qsort(a, 0, 9); for (i = 0; i < 10; i++) printf("%d,", a[i]); return 0; }
直接插入排序:
void InsertionSort(ElementType A[], int N)
{
int j, P;
ElementType tmp;
for (P = 1; P < N; P++)
{
tmp = A[P];
for (j = P; j > 0 && A[j - 1] > tmp; j--)//若条件已满足,此时j的值已减一
A[j] = A[j - 1];
A[j] = tmp;
}
}
对于快速排序的分析:
最坏情况:枢纽元素每次都是第一个,则时间复杂度为O(N2)。
最好情况:枢纽元素每次都是中间,则时间复杂度为O(N*logN)。
平均情况:O(N*logN)
排序的一般下界:任何只用到比较的算法在最坏情况下需要Ω(N*logN)次比较,因此归并排序和堆排序在一个常数因子范围内是最优的,进一步,证明在平均情况下,快速排序在相差一个常数因子的范围内平均最优的。
相关文章推荐
- OC学习之道:数据结构中几种常见的排序算法:选择排序,插入排序.快速排序
- 数据结构实现(插入排序、快速排序、统计排序类模板)
- 【数据结构】常用比较排序算法(包括:选择排序,堆排序,冒泡排序,选择排序,快速排序,归并排序)
- 数据结构试验-快速排序-堆排序
- 数据结构-排序算法详解(插入排序,希尔排序,堆排序,归并排序,快速排序,桶式排序)
- 【数据结构第八周】排序(下)【快速排序】
- 数据结构--冒泡、快速排序
- 数据结构(冒泡、快速、插入等排序)PHP && JAVA --面试技巧
- 浅谈数据结构-交换排序(冒泡、快速)
- C语言基本数据结构之五(折半插入,堆排序,冒泡排序,快速排序,并归排序)
- 数据结构与算法:C++实现快速排序
- 数据结构-快速排序
- 数据结构练习:快速排序
- [数据结构]第八次作业:快速排序
- 数据结构排序之快速排序
- 重学数据结构——快速排序,二分法查找
- 《常见算法和数据结构》元素排序(6)——重头戏:快速排序
- 数据结构--查找&&排序(快速复习)
- 数据结构复习 快速排序个人总结
- 数据结构学习笔记3.2—快速排序