排序算法总结

冒泡排序算法

核心思想:将无序表中的所有记录,通过两两比较关键字,得出升序序列或者降序序列。

核心代码(以升序为例):

    for(int i=0;i<arr.size();i++)
    {
        for(int j=0;j<arr.size()-i-1;j++)
        {
            if(arr[j]>arr[j+1])
                swap(arr[j],arr[j+1]);
        }
    }

选择排序

简单选择排序

核心思想:对于具有 n 个记录的无序表遍历 n-1 次,第 i 次从无序表中第 i 个记录开始,找出后序关键字中最小的记录,然后放置在第 i 的位置上。

核心代码(以升序为例):

void select_sort(vector<int>&arr)
{
    for(int i=0;i<arr.size();i++)
    {
        int min=arr[i];
        int j=i+1;
        int count=i;
        while(j<arr.size())
        {
            if(arr[j]<min)
            {
                min=arr[j];
                count=j;
            }
            j++;
        }
        if(count!=i)
        {
            int temp=arr[i];
            arr[i]=arr[count];
            arr[count]=temp;
        }
    }
}
树型选择排序

核心思想:所有记录采取两两分组,筛选出较小(较大)的值;然后从筛选出的较小(较大)值中再两两分组选出更小(更大)值,依次类推,直到最后选出一个最小(最大)值。同样可以采用此方式筛选出次小(次大)值等。

举例分析

   整个排序的过程,可以用一棵具有 n 个叶子结点的完全二叉树表示。例如对无序表{49,38,65,97,76,13,27,49}采用树形选择的方式排序,过程如下:首先将无序表中的记录采用两两分组,筛选出各组中的较小值(如图中的(a)过程);然后将筛选出的较小值两两分组,筛选出更小的值,以此类推(如图中的(b)(c)过程),最终整棵树的根结点中的关键字即为最小关键字:
在这里插入图片描述
筛选出关键字 13 之后,继续重复此方式找到剩余记录中的最小值,此时由于关键字 13 已经筛选完成,需要将关键字 13 改为“最大值”,继续重复此过程,如下图所示:
在这里插入图片描述

插入排序

直接插入排序

核心思想:在添加新的记录时,使用顺序查找的方式找到其要插入的位置,然后将新记录插入。

核心代码

void Insert_Sort(vector<int>&arr)
{
    for(int i=1;i<arr.size();i++)
    {
        if(arr[i]<arr[i-1])
        {
            int j=i-1;
            int a=arr[i];
            while(j>-1&&a<arr[j])
            {
                arr[j+1]=arr[j];
                j--;
            }
            arr[j+1]=a;
        }
    }
}
折半插入排序算法

核心思想:直接插入排序采用的是顺序查找的方式,而在查找表中数据本身有序的前提下,可以使用折半查找来代替顺序查找,这种排序的算法就是折半插入排序算法。

核心代码:

void Insert_Sort_(vector<int>&arr)
{
    for(int i=1;i<arr.size();i++)
    {
        if(arr[i]<arr[i-1])
        {
            int j=i-1;
            int a=arr[i];
            int low=0;
            int high=j;
            while(low<=high){
                int mid=(low+high)/2;
                if(arr[mid]>a)
                    high=mid-1;
                else
                    low=mid+1;
            }
            for (j=i; j>low; j--) {
            arr[j]=arr[j-1];
            }
            arr[low]=a;
        }
    }
}

希尔排序

核心思想:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的。

举例分析:
   以n=10的一个数组49, 38, 65, 97, 26, 13, 27, 49, 55, 4为例

第一次 gap = 10 / 2 = 5
在这里插入图片描述
分别对(1A,1B);(2A,2B)…等子序列进行直接插入排序。
第二次 gap = 5 / 2 = 2
在这里插入图片描述
分别对子序列(1A,1B,1C,1D,1E)、(2A,2B,2C,2D,2E)进行直接插入排序
第三次 gap = 2 / 2 = 1
在这里插入图片描述
第四次 gap = 1 / 2 = 0 排序完成得到数组
在这里插入图片描述
核心代码:

void easy_shellsort(int a[], int n)
{
	int i, j, gap;

	for (gap = n / 2; gap > 0; gap /= 2)
		for (i = gap; i < n; i++)
			for (j = i - gap; j >= 0 && a[j] > a[j + gap]; j -= gap)
				Swap(a[j], a[j + gap]);
}

归并排序

核心思想:将两个有序的数列合并成一个大的有序的序列。通过递归,层层合并,即为归并,归并排序的算法效率仅次于快速排序,是一种稳定的算法,需要建立两倍的数组空间,一般用于对总体而言无序,但是各子项又相对有序【并不是完全乱序】的情况比较适用。

核心代码:

void merge_array(vector<int>&arr,int low,int middle,int high,vector<int>&res)
{
    int i=low;
    int j=middle+1;
    int low_end=middle;
    int high_end=high;
    int count=0;
    while(i<=low_end&&j<=high_end){
        if(arr[i]<arr[j])
        {
            res[count]=arr[i];
            i++;

        }
        else {
            res[count]=arr[j];
            j++;
        }
        count++;
    }
    while(i<=low_end)
    {
        res[count]=arr[i];
        i++;
        count++;
    }
    while(j<=high_end)
    {
        res[count]=arr[j];
        j++;
        count++;
    }
    for(int i=0;i<count;i++){
        arr[low+i]=res[i];
    }
}

void merge_sort(vector<int>&arr,int low,int high,vector<int>&res)
{
    if(low<high){
        int middle=(low+high)/2;
        merge_sort(arr,low,middle,res);
        merge_sort(arr,middle+1,high,res);
        merge_array(arr,low,middle,high,res);
    }
}

算法分析:
   可以数组分为二组。依次类推,再将两组分成4组,当分出来的小组只有一个数据时,可以认为这个小组组内已经达到了有序,然后再合并相邻的二个小组就可以了。这样通过先递归的分解数列,再合并数列就完成了归并排序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值