常用排序算法

一、冒泡排序

原理: 第一遍从0-n-1遍历,比较相邻元素,最后一个位置确定;第二遍从0-n-2遍历,比较相邻元素,倒数第二个位置被确定;一直遍历直到每个位置都被确定。

数据是反序时,耗费时间最长O(n²);
数据是正序时,耗费时间最短O(n)

是一种稳定的排序算法。
在这里插入图片描述

/* 力扣代码 */
class Solution{
public:
    vector<int> sortArray(vector<int>& nums) {
        int len = (int)nums.size();
        
        for(int i=0;i<=len-1;i++)
        {
            for(int j=0;j<len-1-i;j++)
            {
                if(nums[j] > nums[j+1])
                {
                    swap(nums[j],nums[j+1]);
                }
            }
        }
        return nums;
    }
};

二、选择排序

原理: 遍历所有的数据,先在数据中找出最大或最小的元素,放到序列的起始,再从余下的数据中继续寻找最大或最小的元素,依次放到序列中,直到所有有序。

平均时间复杂度为O(n²)

是一种不稳定的排序算法。
在这里插入图片描述

/* 力扣代码 */
class Solution{
public:
    vector<int> sortArray(vector<int>& nums)
    {
        int len = nums.size();
        for(int i=1;i<len;i++)
        {
            int k = i-1;
            for(int j=i;j<len;j++)
            {
                if(nums[j] < nums[k])
                {
                    k = j;
                }
            }
            if(k != i-1)
            {
                swap(nums[k],nums[i-1]);
            }
        }
        return nums;
    }
};

三、快速排序

原理: 从数组中选择一个元素作为中轴元素,一般可选第一个,把数组中小于中轴的元素放在其左边,大于中轴的元素放在其右边,之后再递归快速排序中轴左右两边的序列直到完成。

最理想的情况是,整个算法的时间复杂度为O(n logn)
最坏的情况是,整个排序算法的时间复杂度为O(n²)

是一种不稳定的排序算法。
在这里插入图片描述

/* 力扣代码 */
class Solution{
public: 
    int quickSort(vector<int>& arr,int left,int right)
    {
    
        if(left >= right)
        {
            return 0;
        }
        int middle = arr[left];
        int begin=left,end=right;
        int start = left;
        while(begin < end)
        {
            while(begin < end && arr[end] >= middle)
            {
                end--;
            }
            while(begin < end && arr[begin] <= middle)
            {
                begin++;
            }
            if(begin != end)
            {
                swap(arr[begin],arr[end]);
            }
        }
        swap(arr[start],arr[begin]);
        quickSort(arr,left,begin-1);
        quickSort(arr,begin+1,right);
        return 0;
    }
    vector<int> sortArray(vector<int>& nums) {
        srand((unsigned)time(NULL));
        quickSort(nums,0,(int)nums.size() - 1);
        return nums;
    }
};

四、堆排序

原理: 将数组当成二叉树构建,且必须满足每一个节点的值都必须大于或等于左右子节点的值。之后将根节点与最后的一个节点交换位置,再对除了最后一个节点外重新排序;一直重复这个步骤,直到排完。

平均时间复杂度为O(n logn),是一种不稳定的排序算法。
在这里插入图片描述

/* 力扣代码 */
class Solution{        
public:
    void max_heap(vector<int>& arr,int start,int end)
    {
        int dad = start;
        int son = dad*2 + 1;
        while(son <= end)
        {
            if(son+1 <= end && arr[son] < arr[son+1])
            {
                son++;
            } 
            if(arr[dad] > arr[son])
            {
                return;
            }
            if(son <= end && arr[son] > arr[dad])
            {
                swap(arr[son],arr[dad]);
                dad = son;
                son = dad*2+1;
            }
        }
    }
    void heap_sort(vector<int>&arr,int len)
    {
        for(int i=len/2-1;i>=0;i--)
        {
            max_heap(arr,i,len-1);
        }
        for(int i=len-1;i>0;i--)
        {
            swap(arr[0],arr[i]);
            max_heap(arr,0,i-1);
        }
    }
    vector<int> sortArray(vector<int>& arr)
    {
        int len = (int)arr.size();
        heap_sort(arr,len);
        return arr;
    }
};

五、插入排序

原理: 假定前i个数据是有序的(起始一般是第一个),接着往后遍历数据,每一个数据都要找到前有序序列中的一个合适位置插入。

数据是反序时,耗费时间最长O(n²);数据是正序时,耗费时间最短O(n)

是一种稳定的排序算法
在这里插入图片描述

/* 力扣代码 */
class Solution{
public:
    vector<int> sortArray(vector<int>& arr)
    {
        int len = arr.size();
        int i=0;
        for(int p=1;p<len;p++)
        {
            i = p - 1;
            int temp = arr[p];
            while(i>=0 && arr[i] > temp)
            {
                 arr[i+1] = arr[i];
                 i--;               
            }    
            arr[i+1] = temp;    
        }
        return arr;    
    }                
};

六、希尔排序

原理: 一般可使用3个增量进行排序,分别是5、3、1,也就是在一组数据里面以5为间隔大小,分别划分出不同的序列分别进行插入排序,再以3为间隔大小,分别划分出不同的序列进行插入排序,最后1就是一次全序列进行插入排序

复杂度下界为O(n log²n),在中等规模的数据中表现良好。

平均时间复杂度为O(n^3/2),是一种不稳定的排序算法
在这里插入图片描述

/* 力扣代码 */
class Solution{
public:      
    void sortShell(vector<int>&arr,int len)
    {
        int i,j,key;
        for(int inc=len/2;inc>0;inc/=2)
        {
            for(i=inc;i<len;i++)
            {
                key = arr[i];
                for(j=i;j>=inc && key < arr[j-inc];j-=inc)
                {
                    arr[j] = arr[j-inc];
                }
                arr[j] = key;
            }
        }
    }
    vector<int>sortArray(vector<int>&arr)
    {
        int len = arr.size();
        sortShell(arr,len);
        return arr;
    }
};

七、归并排序

原理: 原理如图所示,先将一个序列一直对半划分,直到不能再划分,当划分完毕就进行合并,合并的时候分别比较左右分区的第一个元素,把较小的那个放到临时数组,一直这样合并直到合并完毕。

最好情况下可将时间复杂度降至O(n)

平均时间复杂度为O(n logn)
在这里插入图片描述

/* 力扣代码 */
class Solution{
public:
    vector<int>tmp;
    /* 划分数组 */
    void msort(vector<int>&nums,int left,int right)
    {
        if(left < right)
        {
            int mid = left+(left+right)/2;
            //划分左边区域
            msort(nums,left,mid);
            //划分右边区域
            msort(nums,mid+1,right);
            //合并
            int i = left,j = mid+1;
            int cnt = 0;
            /* 合并数组/ */
            while(i<=mid && j<=right)
            {
                if(nums[i] <= nums[j])
                {
                    tmp[cnt++] = nums[i++];
                }
                else
                {
                    tmp[cnt++] = nums[j++];
                }
            }
            /* 合并左分区剩余序列 */
            while(i <= mid)
            {
                tmp[cnt++] = nums[i++];
            }
            /* 合并右分区剩余序列 */
            while(j <= right)
            {
                tmp[cnt++] = nums[j++];
            }
            /* 将排好的数组再放到原数组 */
            for(int i=0;i<(right-left+1);i++)
            {
                nums[i+left] = tmp[i];
            }
        }
        else
            return;
    }

    vector<int>sortArray(vector<int>&nums)
    {
        int len = nums.size();
        tmp.resize((int)nums.size(), 0);
        msort(nums,0,len-1);
        return nums;
    }
};
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值