排序算法

Posted foodie-nils

tags:

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

内部排序

  -插入排序

    -直接插入排序

    -折半插入排序

    -希尔排序

  -交换排序

    -冒泡排序

    -快速排序

  -选择排序

    -简单选择排序

    -堆排序

  -归并排序

  -基数排序

外部排序

  -多路归并排序

 

1.直接插入排序

  算法思路:每次将一个待排序的记录按其关键字大小插入到前面已排好序的子序列中,指导全部记录插入完成。

  性能分析:

      空间复杂度O(1)

      时间复杂度O(n^2)

      算法稳定

      适用于顺序表和链表,使用链表的时候可以重前向后查找插入位置

  

void InsertSort(int arr[],int n){
    int i,j;
    for(int i=2;i<=n;i++){        // arr[0]不存内容,从1开始存起,arr[0]后面会作为哨兵使用 
        if(arr[i]<arr[i-1]){
            arr[0]=arr[i];
            for(int j=i-1;arr[0]<arr[j],j--){
                arr[j+1]=arr[j];
            }
            arr[j+1]=arr[0];
        } 
    }
}

 

2.折半插入排序

  算法思路:和插入排序一样,只是在查找插入位置的时候采用折半查找找到插入位置,找到以后一次性移动元素。注意这里采用的是折半查找,因此这种排序算法只适用于顺序表。

  算法时间复杂度:O(n^2)

void InsertSort_Binary_Search(int arr[],int n){
    int i,j,low,heigh;
    for(i=2;i<=n;i++){
        arr[0]=arr[i];
        low=1;
        heigh=i-1;
        while(low<=heigh){
            int mid=(low+heigh)/2;
            if(arr[mid]>arr[0])
                heigh=mid-1;
            else                //mid<=arr[0]的时候low=mid+1保证算法的稳定性        
                low=mid+1;
        }
        for(j=i;j>low;j--){
            arr[j]=arr[j-1];
        }
        arr[low]=arr[0];
    }
}        

 

 3.希尔排序

  分析:插入排序在序列初始基本有序的时候,算法时间复杂度接近O(N),希尔排序正式基于这一点改进而来的

  思路:把待排序序列中的元素按照[i,i+d,i+2d...]分为若干个子表对每个子表进行直接插入排序,不断降低d的大小,使表基本有序,然后采用一次插入排序,即d取1.希尔提出的d取d1=n/2,di=d(i-1)/2(向下取整)。

  性能分析:

      空间复杂度O(1)

      当n在某个范围时,时间复杂度O(n^1.3),最坏情况下O(n^2)

      由于相同关键字会划分到不同子表,因此不稳定。

      仅适用于顺序存储。

void ShellSort(int arr[],int n){
    for(int d=n/2;d>=1;d=d/2){
        for(int i=d+1;i<=n;i++){
            if(arr[i]<arr[i-d]){
                arr[0]=arr[i];        //arr[0]不是哨兵,只是用来暂存数据元素 
                int j;
                for(j=i-d;arr[j]>arr[0]&&j>0;j-=d){
                    arr[j+d]=arr[j];
                }
                arr[j+d]=arr[0];
            }
        }
    }
}

 

 4.冒泡排序

  算法思路:从第一个元素开始,依次比较相邻的两个元素,如果前面的元素大于后面的元素,则交换他们的次序,一趟下来最大的元素的位置就确定了,依次类推,第二趟的时候就确定了第二大元素的位置,进行n-1躺就能确定所有元素的位置。

  性能分析:

      空间复杂度O(1)

      时间复杂度最好O(n),最坏、平均O(n^2)

      算法稳定

  

void BubbleSort(int arr[],int n){
    for(int i=n-1;i>0;i--){
        int flag=0;
        for(int j=0;j<i;j++){
            if(arr[j]>arr[j+1]){
                int temp=arr[j+1];
                arr[j+1]=arr[j];
                arr[j]=temp;
                flag=1;
            }
        }
        if(flag==0)        //如果某一趟冒泡没有发生交换,则表示序列已经有序 
            break;
    }
}

 

5.快速排序

  算法思路:每次选择一个元素pivot作为枢轴,将比pivot大的元素放到他的右边,比pivot小的元素放到他的左边,从而确定了pivot的位置。将pivot左右两个子表进行同样的操作,循环递归,直至表长度为1或0. 

  性能分析:

      空间复杂度和递归调用深度有关,最好、平均O(logn),最坏O(n)

      时间复杂度和划分是否对称有关,最坏O(n^2),最好、平均O(nlogn)

      算法不稳定

      快速排序是所有内部排序中算法性能最好的排序

 

int Partition(int arr[],int low,int high){
    int pivot;
    pivot=arr[low];
    while(low<high){
        while(high>low&&arr[high]>=pivot)
            high--;
        arr[low]=arr[high];
        while(low<high&&arr[low]<=pivot)
            low++;
        arr[high]=arr[low];
    }
    arr[low]=pivot;
    return low;
}
void QuickSort(int arr[],int low,int high){
    if(low<high){
        int pivot=Partition(arr,low,high);
        QuickSort(arr,low,pivot-1);
        QuickSort(arr,pivot+1,high);
    }
} 

 

6.简单选择排序

  算法思路:每次在待排序序列中选取一个最小元素放入已排好序列最后,总共进行n-1趟就能完成排序

  性能分析:

      空间复杂度O(1)

      时间复杂度O(n^2)

      算法不稳定

void SelectSort(int arr[],int n){
    for(int i=0;i<n-1;i++){
        int min=i;
        for(int j=i+1;j<n;j++){
            if(arr[min]>arr[j]){
                min=j;
            }
        }
        int temp=arr[i];
        arr[i]=arr[min];
        arr[min]=temp;
    }
}

 

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

算法排序之堆排序

快速排序-递归实现

从搜索文档中查找最小片段的算法?

在第6731次释放指针后双重免费或损坏

TimSort算法分析

以下代码片段的算法复杂度