排序算法总结----比较类排序

概述:排序算法可分为比较性的排序,以及运算性的排序;这里详细介绍这些排序的原理,性能,实现,以及应用场合。

前面是维基百科的介绍,这里介绍几个比较典型的算法。

理论

交换排序

选择排序

插入排序

归并排序

分布排序

并发排序

混合排序

其他

以下介绍典型的算法:::::----》》》》

比较排序

一:快速排序(交换排序2号)

1:原理

采用了分治思想,在序列A[p...r]中选取一个元素,当然这里是用了p或者r处的元素(规格一致);找到该元素的,满足前面的值都比它小,后面的都比它大;同理让子序列递归下去。

2:性能

最坏时间复杂度:θ(n²)---出现在序列是顺序的,导致极度不平衡划分,1:0效果划分。

最好时间复杂度:θ(nlog2(n))---出现在每次划分都是在中间处;

中间状态:比如划分比例是a:b;则复杂度就是a/(b+a);b/(b+a)取大的(假设为a/(b+a)),则复杂度为θ(nlog(b+a)/a(n))其实也可以是θ(nlog(n))

平均复杂度也就是θ(nlog(n));

空间复杂度为:O(logn)----递归引起;

3:应用

实际排序中比较好,适合对平均时间复杂度有要求,要求原址排序,且隐含因子比较小;应用场景多。百万数量级以下合适

4:实现----c++代码实现如下

void exchang(int * sort,int i,int j)
{
    int temp=0;
    temp=sort[i];
    sort[i]=sort[j];
    sort[j]=temp;
}
int partition(int *sort ,int p,int r)
{
    int x=sort[r];
    int i=p-1;
    for(int j=p;j<r;j++)//p--->r-1
    if(sort[j]<=x)
    {
        i++;
        if(i!=j)
            exchang(sort,i,j);
    }
    if((i+1)<r)
        exchang(sort,i+1,r);
    return i+1;
}
//栈溢出,原因是它递归太深了
void QuickSort(int *sort ,int sn,int en)
{
    if(sn<en)
    {
        int q=partition(sort,sn,en);
        QuickSort(sort,sn,q-1);
        QuickSort(sort,q+1,en);
    }
}

第二:插入排序

第三:归并排序

第四:堆排序

1:原理

2:性能

3:应用

4:实现

//数据交换
void Exchang(int * sort,int i,int j)
{
    int temp=0;
    temp=sort[i];
    sort[i]=sort[j];
    sort[j]=temp;
}
//修改堆
void MaxHeapIfy(int *ops,int i,int heapsize)
{
    int l=2*i+1;//left
    int r=2*(i+1);

    int max;
    if((l<=heapsize-1)&&ops[l]>ops[i])
        max=l;
    else
        max=i;
    if((r<=heapsize-1)&&ops[r]>ops[max])
        max=r;
    if(max!=i)
    {
        exchang(ops,i,max);
        maxheapify(ops,max,heapsize);
    }

}
//构建堆
void BuildMaxHeap(int *ops,int length)
{
    for(int i=(length-2)/2;i>=0;i--)
        maxheapify(ops,i,length);
}
//树也有递归,但是树本身不会那么深。
void HeapSort(int *ops,int length)
{
    buildmaxheap(ops,length);
    for(int i=length-1;i>=1;i--)
    {
        exchang(ops,0,i);
        length--;
        maxheapify(ops,0,length);
    }
}

第五:选择排序

1:原理

通过比较,先找出最大值或者最小值,找到后就将其放到队首,这样下来就是顺序的了。

2:性能

最差时间复杂度О(n²)

最优时间复杂度О(n²)

平均时间复杂度О(n²)

空间复杂度:1

3:应用

n小时比较合适,算法简单,是比较后排序;使用场合少

4:c++实现

void SelectionSort(int* unsorted,int length)
{
    for (int i = 0; i < length; i++)
    {
        int min = unsorted[i], min_index = i;
        for (int j = i; j < length; j++)
        {
            if (unsorted[j] < min)//选择最小值处
            {
                min = unsorted[j];
                min_index = j;
            }
        }
        if (min_index != i)//选出后交换
        {
            int temp = unsorted[i];
            unsorted[i] = unsorted[min_index];
            unsorted[min_index] = temp;
        }
    }
}

第六:冒泡排序(交换排序1号)

1:原理

通过比较,不断冒充最大值或者最小值,它和选择排序相似,选择排序是先找最小值,再交换;而冒泡是比较一次就会交换,从效率上将,冒泡排序不如选择排序。

2:性能

最差时间复杂度

最优时间复杂度为什么是这个值,因为可以往后冒泡,产生的结果就可以达到这个效果。。。。

平均时间复杂度

3:应用

应用类似插入算法

4:实现

1)往前冒泡

void BubbleSort(int *unsorted,int length)
{
    for (int i = 0; i <length ; i++)
    {
        for (int j = i; j < length; j++)
        {
            if (unsorted[i] > unsorted[j])
            {
                int temp = unsorted[i];
                unsorted[i] = unsorted[j];
                unsorted[j] = temp;
            }
        }
    }
}

2)往后冒泡(C#)

public void bubbleSort(int arr[]) {
    boolean didSwap;
    for(int i = 0, len = arr.length; i < len - 1; i++) {
        didSwap = false;
        for(int j = 0; j < len - i - 1; j++) {
            if(arr[j + 1] < arr[j]) {
                swap(arr, j, j + 1);
                didSwap = true;
            }
        }
        if(didSwap == false)
            return;
    }
}

第七:希尔排序

1:原理

通过分组排序,比如以某个增量d,也就是分成d组,在d组内中进行插入排序;不断让d减小,使的最后为1,也就是到达了直接排序效果;和插入比较有何体现呢?插入最坏是O(n²),最好是O(n)。但是在n小时相差不大,这就是用分组减小n,而后期的组数少了,但是排序好了,则会走向好的情况,故而总体是效率高了。

2:性能

最坏时间复杂度:O(ns),s大致是1~2;

平均时间复杂度:O(nlog(n));

最好时间复杂度:O(n)

注:n较大时目前一般是n1.25到1.6n1.25之间。

3:应用

它优于插入算法,不稳定。

4:实现

//
//采取2的k次幂-1是最佳的,k表示第几趟
//最后一个步长是1
//k是趟数,这个可以自己设定。。。。
//

//通俗版本,比较简单
void ShellSort(int* a, int length)
{
    int gap; //增量,,组
    for(gap = 3; gap >0; gap--)  //3组。。。自己也可以设定大一点组,
    {
        for(int i=0; i<gap; i++)  //显然这种分组的步长是1
        {
            for(int j = i+gap; j<length; j=j+gap)  //
            {
                if(a[j]<a[j-gap])
                {
                    int temp = a[j];
                    int k = j-gap;
                    while(k>=0&&a[k]>temp)
                    {
                        a[k+gap] = a[k];
                        k = k-gap;
                    }
                    a[k+gap] = temp;
                }
            }
        }
    }
}
//通用版本,,比较灵活
void ShellSort(int a[], int n , int d[] ,int numOfD)
{

    int i,j,k;
    int val;
    int span;    //增量
    for(int m=0; m<numOfD; m++)        //m趟
    {
        span=d[m];
        for(k=0; k<span; k++) //span个小组
        {
            //组内进行直接插入排序 ,区别在于每次不是增加1,而是增加span
            for(i=k; i<n-span; i+=span)
            {
                val=a[j+span];
                j=i;
                while(j>-1 && val<a[j])
                {
                    a[j+span]=a[j];
                    j=j-span;
                }

                a[j+span]=val;
            }
        }
    }
}

第八:鸡尾酒排序

1:原理

在冒泡基础上改进,让单向冒泡变成双向冒泡;结束时是两个冒泡起点重合时。

2:性能

最坏情况还是和冒泡一致;n的2次方

但是好的和插入相似了。为n;它比直接冒泡要好;

空间复杂度:1

3:应用

性能和直接插入算法相似,故而和插入算法应用相似。

4:实现

void CocktailSort(int * list, int list_length)
{
    int bottom = 0;
    int top = list_length - 1;
    int bound = 0; //优化循环次数,记录已经排序的边界,减少循环次数
    while(bottom!=top) //表示已全部冒泡完了,就是已经成为顺序了
    {
        for(int i = bottom; i < top; i = i + 1)
        {//顺冒泡
            if(list[i] > list[i+1])
            {
                swap(list[i], list[i+1]); 

                bound = i;
            }
        }
        top = bound;
        for(int i = top; i > bottom; i = i - 1)
        {//反顺冒泡
            if(list[i] < list[i-1])
            {
                swap(list[i], list[i-1]);
                bound = i;
            }
        }
        bottom = bound;
    }
}

第九:地精排序

1:原理

在冒泡基础上改进的,它的效果和插入排序相似,号称是简单的排序算法,算法实现非常短。

2:性能

性能和插入排序一样

3:应用

应用和插入排序一样

4:实现

void GnomeSort(int* unsorted,int length)
{
    int i = 0;
    while (i < length)//到达最后一个表示完成了
    {
        if (i == 0 || unsorted[i - 1] <= unsorted[i])
        {//表示能前进的条件,i=0或者是没有交换
            i++;
        }
        else
        {//发生交换了
            int tmp = unsorted[i];
            unsorted[i] = unsorted[i - 1];
            unsorted[i - 1] = tmp;
            i--;
        }
    }
}

第十:奇偶排序

1:原理

选取奇数,和它相邻比较,排序;同样对偶数也这样,最后达到没有交换了,此时就是顺序的了

2:性能

平均时间复杂度:O(n2);

最好时间复杂度:O(n);

最差时间复杂度:O(n2);

可以看到有点像插入排序了;不稳定

3:应用

和插入排序应用相似。。。

4:实现

void OddEvenSort(int * szArray,int length)
{
    bool sorted = false;
    while (!sorted)
    {
        sorted = true;
        for (int i = 1; i < length - 1; i += 2)
        {  //偶数排
            if (szArray[i]>szArray[i + 1])
            {
                int tmp = szArray[i];
                szArray[i] = szArray[i+1];
                szArray[i+1] = tmp;
                sorted = false;
            }
        }
        for (int i = 0; i < length - 1; i+= 2)
        {  //奇数排
            if (szArray[i]>szArray[i + 1])
            {
                int tmp = szArray[i];
                szArray[i] = szArray[i+1];
                szArray[i+1] = tmp;
                sorted = false;
            }
        }
    }
}

第十一:梳排序

1:原理

它是基于冒泡和插入排序的结合品,选取了适合的比率,进行冒泡。

2:性能

最差时间复杂度
      最优时间复杂度

平均时间复杂度,p是比率;

空间复杂度:1。。。。不稳定

3:应用

类似插入算法应用

4:实现

void CombSort(int *arr, int size)
{

  double shrink_factor = 1.247330950103979;//1.3比率
  int gap = size;
  int swapped = 1;
  int swap;
  int i;

  while ((gap > 1) || swapped)
  {
    if (gap > 1)
    {
        gap = gap / shrink_factor;//计算间距
    }
 //直到gap为1时表示已经再距离上已经是到达了
    //此时就和冒泡一致了,外循环加内循环了,直到不再交换为止。。。
    swapped = 0;
    i = 0;

    while ((gap + i) < size)
    {
      if(arr[i]-arr[i+gap] > 0)
      {
        swap = arr[i];
        arr[i] = arr[i+gap];
        arr[i+gap] = swap;
        swapped = 1;
      }
      ++i;
    }
  }
}

下一遍----->运算类的排序<-------下一篇

排序算法总结----比较类排序,布布扣,bubuko.com

时间: 2024-10-19 03:05:06

排序算法总结----比较类排序的相关文章

排序算法总结----运算类排序

运算排序 第一:计数排序 1:原理 对于每个输入数,确定小于该数的个数.这样可以直接把数放在输出数组的位置. 2:性能 最差时间复杂度 最优时间复杂度 平均时间复杂度 最差空间复杂度 注:稳定算法 3:应用 适合0~100的范围的数,当然可以和基排序结合而扩展数的范围. 4:实现 void CountingSort(int *A, int *B, int array_size, int k) { int i, value, pos; int * C=new int[k+1]; for(i=0;

详谈排序算法之选择类排序(两种方法实现堆排序)

   今天我们再来讨论一下选择类排序,选择类排序分为:简单排序,树形选择排序和堆排序.但我们主要说的是简单和堆排序两个,因为树形选择排序使用了较多的辅助空间,以及和∞进行多余比较,为弥补树型选择排序的这些缺点, J.W.J.Williams 在 1964 年提出了进一步的改进方法,即堆排序.对于我个人而言..一开始并不是很理解它的算法思想,纠结了许久.在网上查找资料的时候发现这位大神的文章思路十分清晰,而且把创建堆以及堆化数组的算法讲解的十分详细.如果有不明白堆排序思路的,可以先看看这篇文章~堆

详谈排序算法之插入类排序(两种思路实现希尔排序)

1. 排序( sorting) 的功能是将一个数据元素的任意序列,重新排列成一个按关键字有序的序列.其确切的定义为: 假设有n个数据元素的序列{R1 , R2 , - , Rn},其相应关键字的序列是{K1 , K2 , - , Kn} ,通过排序要求找出下标 1 , 2 , - , n的一种排列p1 , p2 , - , pn,使得相应关键字满足如下的非递减(或非递增)关系Kp1 ≤ Kp2 ≤ - ≤ Kpn这样,就得到一个按关键字有序的纪录序列{ Rp1 , Rp2 , - , Rpn }

详谈排序算法之交换类排序(两种方法实现快速排序【思路一致】)

1.冒泡排序    起泡排序的思想非常简单.首先,将 n 个元素中的第一个和第二个进行比较,如果两个元素的位置为逆序,则交换两个元素的位置:进而比较第二个和第三个元素关键字,如此类推,直到比较第 n-1 个元素和第 n 个元素为止:上述过程描述了起泡排序的第一趟排序过程,在第一趟排序过程中,我们将关键字最大的元素通过交换操作放到了具有 n 个元素的序列的最一个位置上.然后进行第二趟排序,在第二趟排序过程中对元素序列的前 n-1 个元素进行相同操作,其结果是将关键字次大的元素通过交换放到第 n-1

常见排序算法——七大比较类排序算法

算法 最坏复杂度 平均复杂度 最好复杂度 空间复杂度 选择排序 O($n^2$) O($n^2$) O($n^2$) O(1) 插入排序 O($n^2$) O($n^2$) O($n$) O(1) 希尔排序 O($nlog(n))$~O($n^2$) O($n^{1.3}$) O($n^2$) O(1) 冒泡排序 O($n^2$) O($n^2$) O(n)(用交换flag改进) O(1) 快速排序 O($n^2$) O($nlog(n)$) O($nlog(n)$) O(log(n))~O(n

各种排序算法的一个类

#include<iostream> #define MAX 100 using namespace std; class Sample { int a[MAX]; int b[MAX]; int n; friend class Process; public: Sample(){n=0;} }; class Process { private: int s_psort(Sample &s,int first,int end); void sift(int k,int m,Sample

排序算法七:选择排序之堆排序

排序算法七:选择排序之堆排序 声明:引用请注明出处http://blog.csdn.net/lg1259156776/ 引言 在我的博文<"主宰世界"的10种算法短评>中给出的首个算法就是高效的排序算法.本文将对排序算法做一个全面的梳理,从最简单的"冒泡"到高效的堆排序等. 上博文讲述了选择排序中的简单排序算法,本文介绍的堆排序是树性选择排序,采用堆这个数据结构来辅助排序. 排序相关的的基本概念 排序:将一组杂乱无章的数据按一定的规律顺次排列起来. 数据

排序算法(4)-线性时间排序

在前面三节排序算法中,我们分别分析了不同策略,思想用于排序,而这些算法都是基于数据间的比较来确定顺序的.假设我不用比较,换一种思路,那么就可以达到时间复杂度为O(n)的排序算法,当然是以付出额外的空间为代价的. 一.基本思想 线性时间排序的算法思想: (1):在计数排序中,利用比x小或等的元素个数和的来确定x位置.比如2 5 4 9 1 6.9比其余5个数都大,那就说明9 在排序后的第6个位置,这样我们只要得到比某个数大的元素个数就能得到元素在排序后数组中的位置了. (2):在桶排序中,是通过映

排序算法总结之希尔排序

一,希尔排序算法介绍 ①希尔排序又称缩小增量排序 ,它本质上是一个插入排序算法.为什么呢? 因为,对于插入排序而言,插入排序是将当前待排序的元素与前面所有的元素比较,而希尔排序是将当前元素与前面增量位置上的元素进行比较,然后,再将该元素插入到合适位置.当一趟希尔排序完成后,处于增量位置上的元素是有序的. ②希尔排序算法的效率依赖于增量的选取 假设增量序列为 h(1),h(2).....h(k),其中h(1)必须为1,且h(1)<h(2)<...h(k) . 第一趟排序时在增量为h(k)的各个元