一句话总结几种排序算法及其稳定性

来源:互联网 发布:cf总是网络异常 编辑:程序博客网 时间:2024/05/21 19:28

排序的稳定性

稳定性: 两记录排序码相等,稳定的排序算法可以保证即使值相等,排序后顺序仍然不变。
因为原序列的顺序可能隐含一些信息,稳定排序算法维持这些信息。

冒泡排序(相邻元素排序调):如若两个数值相等,则不会发生交换,故该排序是稳定的。
选择排序(每次选最小的排序):如果较小的元素出现在一个和当前元素相等的元素后面,那么交换后稳定性就被破坏了,故该排序是稳定的。
插入排序(在已经有序的队列里插值):比较是从有序序列的末尾开始,
如果碰见一个和插入元素相等的,那么插入元素把想插入的元素放在相等元素的后面。插入排序是稳定的。
快速排序(从左往右,基数右移,小于基数前调):快速排序是一个不稳定的排序算法,不稳定发生在基数元素和a[j] 交换的时刻。详见下文快速排序的介绍
归并排序(将序列递归地分成短序列):稳定的排序算法。
希尔排序(shell)(按照不同步长对元素进行插入排序):不稳定的排序算法
堆排序(节点排序):当为n /2-1, n/2-2, …1这些个父节点选择元素时,就会破坏稳定性。有可能第n/2个父节点交换把后面一个元素交换过去了,而第n/2-1个父节点把后面一个相同的元素没有交换,这2个相同的元素之间的稳定性就被破坏了 。

综上,选择排序、快速排序、希尔排序、堆排序等不是稳定的排序算法,而 冒泡排序、插入排序、归并排序和基数排序等是稳定的排序算法。
这部分详细见百度百科

几种排序算法总结

  • BUBBLE 冒泡排序

从左往右,找到最大的移至最后

示例代码:

int i,j,k;for(i=0;i<n-1;i++) //找出n-1个最大的放在右边{    for(j=0;j<n-1-i;j++) //排好的序列逐步从右向左推进{    if(ap[j]>ap[j+1])    {        swap(ap[j],ap[j+1]); //交换    }}}
  • SELECT 选择排序

从左往右,找到最小的移至前面,排好的序列由左向右推进。

示例代码:

void sort (int array[],int n){int i,j,k,t;for (i=0;i<n-1;i++) //需要n-1次{    k=i; //k保存最小的值    for(j=i+1;j<n;j++) //从左向右推进        if(array[k]>array[j])    k=j; //k保存最小的值    swap(array[k],array[i]);//交换}}
  • INSERT 插入排序

从左往右,依次为该数找到相应的位置插入前面序列

  • MERGE 归并排序

将数列多次分半,直到每组有两个数,对每小组进行排序,成为有序数列,再往前合并其他小组

  • QUICK 快速排序 O(N*logN)

visualgo里的排序流程
for each (unsorted) partition set first element as pivot
for i = pivotIndex + 1 to rightmostIndex
if element[i] < element[pivot]
swap(i, storeIndex);
storeIndex++ swap(pivot, storeIndex - 1)

先从数列中取出一个数作为基准数。一般为第一个数。
分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。
再对左右区间重复第二步,直到各区间只有一个数。
总结:用i,j两个数左右搜索,将第一个值存入X,右往左找比X小的数,左往右找X大的数,填坑,i,j逼进,直到ij相等。此时,左边是比X小的数,右边是比X大的数

示例
主函数

int main(){    int array[10],k;    int len;//要排列的数的长度,不能超过10个    cout<<"the len";    cout<<endl;    cin>>len;    cout<<"The orginal array are:"<<endl;    for(int k=0; k<len; k++)        cin>>array[k];    quickSort(array,0,len-1);    cout<<"The sorted array are:"<<endl;    for(int k=0; k<len; k++)        cout<<array[k]<<" ";    cout<<endl;    system("pause");    return 0;}

版本一

void quickSort(int s[], int l, int r) //主函数{if (l< r){    int i = l, j = r, x = s[l];while (i < j) //直到i==j{while(i < j && s[j]>= x) // 从右向左找第一个小于x的数j–;if(i < j)s[i++] = s[j];//s[i] = s[j],++i;while(i < j && s[i]< x) // 从左向右找第一个大于等于x的数i++;if(i < j)s[j–] = s[i];//s[j] = s[i],–j;}s[i] = x;quickSort(s, l, i – 1); // 递归调用quickSort(s, i + 1, r);}}

版本二:

//一次划分int Partition(int r[], int start, int end){    if(r==NULL ||start <0||end < start)        throw new std::exception("Invailid Paramater");    //初始化    int i=start;    int j=end;    int temp;    while (i<j)    {        while (i<j && r[i]<= r[j])            j--;         if (i<j) //右往左找到大值,交换值且i右移        {            //将较小记录交换到前面            swap(r[i],r[j]);            i++;        }        while (i<j && r[i]<=r[j])            i++; //左侧扫描        if (i<j)        {            swap(r[i],r[j]); //将较大记录交换到后面            j--;        }    }    return i; //i为轴值记录的最终位置}//快速排序void quickSort(int r[], int start, int end){    if (start<end)    {        //递归结束        int pivot=Partition(r, start, end); //一次划分        quickSort(r, start, pivot-1);//递归地对左侧子序列进行快速排序        quickSort(r, pivot+1, end); //递归地对右侧子序列进行快速排序    }}
0 0