实用且有效的排序算法

Posted Charles梦想家

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实用且有效的排序算法相关的知识,希望对你有一定的参考价值。

 

排序概念

排序是计算机内经常进行的一种操作,其目的是将一组“无序”的数据元素调整为“有序”的数据元素。

  • 排序是数据元素从无序到有序的过程

  • 排序具有稳定性,是选择排序算法的因素之一

  • 比较和交换是排序的基本操作

  • 排序的时间性能是区分排序算法好坏的主要因素。

排序中的关键环节:

  • 比较:任意两个数据元素通过比较操作确定先后次序

  • 交换:数据元素之间需要交换才能得到预期结果

  • 内排序:整个排序过程不需要访问外存便能完成

  • 外排序:待排序的数据元素数量较多,整个序列的排序过程不可能在内存中完成

  • 辅助存储空间:为完成排序操作需要的额外的存储空间,必要时可以“空间换时间”。
    选择排序算法

思想步骤:

每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。

设数组为a[0…n-1]。

  • 初始时,数组为无序区为a[0..n-1]。令i=0

  • 在无序区a[i…n-1]中选取一个最小的元素,将其与a[i]交换。交换之后a[0…i]就形成了一个有序区。

  • i++并重复第二步直到i=n-1。

算法实现:

//升序排列void selectsort(int * array,int len){int i,j;int minindex=0;for(i=0;i<len-1;i++){minindex=i;   for(j=i+1;j<len-1;j++)     {        if(array[minindex]>array[j])        {             minindex=j;        }     }     //交换元素     if(minindex!=i)     {        int temp=array[i];        array[i]=array[minindex];        array[minindex]=temp;     } }}

冒泡排序算法

       思想步骤:

  • 比较相邻的元素。如果第一个元素比第二个元素大,就交换他们两个。

  • 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。

  • 针对所有的元素重复以上的步骤。持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

       算法实现:

void bubblesort(int * array,int len){   int i,j;   int temp;   for(i=0;i<len-1;i++)     {     for(j=0;j<len-1-i;j++)         {             if(array[j+1]<array[j])             {                    temp=array[j];                    array[j]=array[j+1];                    array[j+1]=temp;             }         }     }}

冒泡优化算法

void BubbleSort(int arr[], int len){  int i = 0;  int tmp = 0;  for (i = 0; i < len - 1; i++)  {    int j = 0;    int flag = 0;    for (j = 0; j < len - 1 - i; j++)    {      if (arr[j]>arr[j + 1])      {        tmp = arr[j];        arr[j] = arr[j + 1];        arr[j + 1] = tmp;        flag = 1;//加入标记      }    }    if (flag == 0)//如果没有交换过元素,则已经有序    {      return;    }  }}

插入排序算法

思想步骤:

设数组为a[0…n-1]。

  • 初始时,a[0]自成1个有序区,无序区为a[1..n-1]。令i=1

  • 将a[i]并入当前的有序区a[0…i-1]中形成a[0…i]的有序区间。

  • i++并重复第二步直到i==n-1。排序完成。

算法实现:

void insertsort(int *array,int len){ int i,j; int temp=-1; int k=-1; for(i=1;i<len-1;i++)   {        k=i; //待插入位置        temp=array[k];        for(j=i-1;(j>=0)&&(array[j]>temp);--j)        {                array[j+1]=array[j]; //元素后移                 k=j;             }          array[k]=temp;   }}

希尔排序算法

思想步骤:

  通过将待排序的元素分为若干个子序列,利用直接插入排序思想对子序列进行排序。然后将该子序列缩小,接着对子序列进行直接插入排序。按照这种思想,直到所有元素都按照关键字有序排列。

算法实现:

void ShellInsert(SqList *L, int c) /*对顺序表L 进行一次希尔排序,c 是增量*/{int i, j;DataType t;for(i=c+1; i<=L->length; i++) /*将距离为c 的元素作为一个子序列进行排序*/{if(L->data[i].key < L->data[i-c].key)/*若后者小于前者,则需移动元素*/{t = L->data[i];for(j=i-c; j>0&&t.key<L->data[j].key; j=j-c)L->data[j+c] = L->data[j];L->data[j+c] = t; /*依次将元素插入到正确的位置*/}}}void ShellInsertSort(SqList *L, int delta[], int m)/*希尔排序,每次调用算法ShellInsert,delta 是存放增量的数组*/{int i;for(i=0; i<m; i++) /*进行m 次希尔插入排序*/{ShellInsert(L, delta[i]);}}

快速排序算法

快速排序采用分治策略,是冒泡排序的一种改进算法。

思想步骤:

先从数列中取出一个数作为基准数(枢轴)。分区过程将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。

再对左右区间重复第二步,直到各区间只有一个数。

void Qsort(int arr[], int low, int high){    if (high <= low) return;    int i = low;    int j = high + 1;    int key = arr[low];    while (true)    {        /*从左向右找比key大的值*/        while (arr[++i] < key)        {            if (i == high){                break;            }        }        /*从右向左找比key小的值*/        while (arr[--j] > key)        {            if (j == low){                break;            }        }        if (i >= j) break;        /*交换i,j对应的值*/        int temp = arr[i];        arr[i] = arr[j];        arr[j] = temp;    }    /*中枢值与j对应值交换*/    int temp = arr[low];    arr[low] = arr[j];    arr[j] = temp;    Qsort(arr, low, j - 1);    Qsort(arr, j + 1, high);}

归并排序算法

归并排序是建立在归并操作上的一种有效的排序算法。

思想步骤:

假设元素的个数是n,将每个元素作为一个有序的子序列,然后将相邻的两个子序列两两合并,得到n/2个长度为2 的有序子序列。继续将相邻的两个有序子序列两两合并,得到n/4个长度为4 的有序子序列。依次类推,重复执行以上操作,直到有序序列合并为 1 个为止。

void Merge(int sourceArr[],int tempArr[], int startIndex, int midIndex, int endIndex){    int i = startIndex, j=midIndex+1, k = startIndex;    while(i!=midIndex+1 && j!=endIndex+1)    {        if(sourceArr[i] > sourceArr[j])            tempArr[k++] = sourceArr[j++];        else            tempArr[k++] = sourceArr[i++];    }    while(i != midIndex+1)        tempArr[k++] = sourceArr[i++];    while(j != endIndex+1)        tempArr[k++] = sourceArr[j++];    for(i=startIndex; i<=endIndex; i++)        sourceArr[i] = tempArr[i];}

 

//内部使用递归void MergeSort(int sourceArr[], int tempArr[], int startIndex, int endIndex){    int midIndex;    if(startIndex < endIndex)    {        midIndex = startIndex + (endIndex-startIndex) / 2;//避免溢出int        MergeSort(sourceArr, tempArr, startIndex, midIndex);        MergeSort(sourceArr, tempArr, midIndex+1, endIndex);        Merge(sourceArr, tempArr, startIndex, midIndex, endIndex);    }}

 

以上是关于实用且有效的排序算法的主要内容,如果未能解决你的问题,请参考以下文章

基础实用算法

10大基础实用算法及其讲解

程序员必须知道的10大基础实用算法及其讲解

程序员必须知道的10大基础实用算法及其讲解

21个常用代码片段

PHP 代码片段