C++ OJ题测试—排序算法效率

 目录


OJ链接

​ 

一、直接插入排序

class Solution {
public:
    vector<int> sortArray(vector<int>& nums) {
        for(int i=0;i<nums.size()-1;i++)
        {
            int end=i;
            int tmp=nums[i+1];
            while(end>=0)
            {
                if(nums[end]>tmp)
                {
                    nums[end+1]=nums[end];
                    --end;
                }
                else
                    break;
            }
            nums[end+1]=tmp;
        }
        return nums;
    }
};

 

二、希尔排序

class Solution {
public:
    vector<int> sortArray(vector<int>& nums) {
        int gap=nums.size();
        while(gap>1){
            gap=gap/3+1;
            for(int i=0;i<nums.size()-gap;i++){
                int end=i;
                int tmp=nums[end+gap];
                while(end>=0){
                    if(nums[end]>tmp){
                        nums[end+gap]=nums[end];
                        end-=gap;
                    }
                    else
                        break;
                }
                nums[end+gap]=tmp;
            }
        }
        return nums;
    }
};

三、直接选择排序

常规: 

class Solution {
public:
    vector<int> sortArray(vector<int>& nums) {
        int i,j,minIndex,temp;
        for(i=0;i<nums.size()-1;i++){
            minIndex=i;
            for(j=i+1;j<nums.size();j++){
                if(nums[j]<nums[minIndex])
                    minIndex=j;
            }
            temp=nums[i];
            nums[i]=nums[minIndex];
            nums[minIndex]=temp;
        }
        return nums;
    }
};

​ 

 第二种:

class Solution {
public:
    vector<int> sortArray(vector<int>& nums) {
        int begin=0,end=nums.size()-1;
        while(begin<end){
            int maxi=begin,mini=begin;
            for(int i=begin;i<=end;i++){
                if(nums[i]>nums[maxi])
                    maxi=i;
                if(nums[i]<nums[mini])
                    mini=i;
            }
            swap(nums[begin],nums[mini]);
            if(begin==maxi)
                maxi=mini;
            swap(nums[maxi],nums[end]);
            ++begin;
            --end;
        }
        return nums;
    }
};

四、 堆排序

class Solution {
public:
    void AdjustDown(vector<int>& a,int n,int parent)
    {
        int child=parent*2+1;
        while(child<n){
            if(child+1<n&&a[child+1]>a[child])
                ++child;
            if(a[child]>a[parent]){
                swap(a[child],a[parent]);
                parent=child;
                child=parent*2+1;
            }
            else{
                break;
            }
        }
    }
    vector<int> sortArray(vector<int>& nums) {
        for(int i=(nums.size()-1-1);i>=0;i--){
            AdjustDown(nums,nums.size(),i);
        }
        int end=nums.size()-1;
        while(end>0){
            swap(nums[0],nums[end]);
            AdjustDown(nums,end,0);
            --end;
        }
        return nums;
    }
};

 

五、冒泡排序

class Solution {
public:
    vector<int> sortArray(vector<int>& nums) {
        for (int j = 0; j < nums.size(); ++j){
            bool exchange = false;
            for (int i = 1; i < nums.size() - j; i++)
            {
                if (nums[i - 1] > nums[i])
                {
                    int tmp = nums[i];
                    nums[i] = nums[i - 1];
                    nums[i - 1] = tmp;
    
                    exchange = true;
                }
            }
    
            if (exchange == false)
            {
                break;
            }
        }
        return nums;
    }
};

六、快速排序

使用C++ sort函数

sort函数是C++标准库中提供的通用排序函数,用于对容器中的元素进行排序。它可以对各种容器(如数组、向量、列表等)中的元素进行排序,包括内置类型和自定义类型。

sort函数的声明如下:

template <class RandomAccessIterator>
void sort(RandomAccessIterator first, RandomAccessIterator last);
  • first:表示排序范围的起始迭代器,指向要排序的第一个元素。
  • last:表示排序范围的结束迭代器,指向要排序的最后一个元素的下一个位置。

sort函数使用的是一种快速排序或归并排序的变体算法,具体取决于实现。它会根据元素的比较运算符(<)来确定元素的顺序。

class Solution {
public:
    vector<int> sortArray(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        return nums;
    }
};

 

 

C语言思路:

class Solution {
public:
    int GetMidIndex(vector<int>& a, int left, int right)
    {
        int mid = (left + right) >> 1;
        if (a[left] < a[mid])
        {
            if (a[mid] < a[right])
            {
                return mid;
            }
            else if (a[left] < a[right])
            {
                return right;
            }
            else
            {
                return left;
            }
        }
        else // a[left] > a[mid]
        {
            if (a[mid] > a[right])
            {
                return mid;
            }
            else if (a[left] > a[right])
            {
                return right;
            }
            else
            {
                return left;
            }
        }
    }
    void QuickSort(vector<int>& a, int begin, int end)
    {
        if (begin >= end)
            return;
    
        int keyi = PartSort3(a, begin, end);
        QuickSort(a, begin, keyi - 1);
        QuickSort(a, keyi + 1, end);
    }
    
    int PartSort3(vector<int>& a, int left, int right)
    {
        int midi = GetMidIndex(a, left, right);
        swap(a[left], a[midi]);
    
        int prev = left;
        int cur = left + 1;
        int keyi = left;
        while (cur <= right){
            if (a[cur] < a[keyi] && ++prev != cur){
                swap(a[prev], a[cur]);
            }
            ++cur;
        }
       swap(a[prev], a[keyi]);
        keyi = prev;
        return keyi;
    }
    vector<int> sortArray(vector<int>& nums) {
        QuickSort(nums,0,nums.size()-1);
        return nums;
    }
};

​ 

三路划分优化效率

​ 

class Solution {
public:
    int GetMidIndex(vector<int>& a, int left, int right)
    {
        int mid = left + (rand()%(right-left));
        if (a[left] < a[mid])
        {
            if (a[mid] < a[right])
            {
                return mid;
            }
            else if (a[left] < a[right])
            {
                return right;
            }
            else
            {
                return left;
            }
        }
        else // a[left] > a[mid]
        {
            if (a[mid] > a[right])
            {
                return mid;
            }
            else if (a[left] > a[right])
            {
                return right;
            }
            else
            {
                return left;
            }
        }
    }

    void QuickSort(vector<int>& a, int begin, int end)
    {
        if (begin >= end)
            return;

        int left = begin;
        int right = end;
        int cur = left + 1;

        int midi = GetMidIndex(a, left, right);
        swap(a[left], a[midi]);
        int key = a[left];

        while (cur <= right)
        {
            if (a[cur] < key)
            {
                swap(a[left], a[cur]);
                ++left;
                ++cur;
            }
            else if (a[cur] > key)
            {
                swap(a[right], a[cur]);
                --right;
            }
            else
            {
                ++cur;
            }
        }

        QuickSort(a, begin, left - 1);
        QuickSort(a, right + 1, end);
    }

    vector<int> sortArray(vector<int>& nums)
    {
        srand(time(0));

        QuickSort(nums, 0, nums.size() - 1);

        return nums;
    }
};
  1.  GetMidIndex:这个方法用于在快速排序的过程中选择一个”基准”元素。它首先随机选择一个索引mid,然后比较数组aleftmidright这三个位置的元素,返回这三个元素中的中位数的索引。这种方式可以有效地避免在处理近乎有序的数组时,快速排序退化为O(n^2)的情况。
  2. QuickSort:这是快速排序的主要方法。它首先调用GetMidIndex方法获取基准元素的索引,然后将基准元素与数组的第一个元素交换位置,接着遍历数组,将小于基准的元素放到左边,大于基准的元素放到右边,等于基准的元素不动。最后,递归地对基准元素左边和右边的子数组进行同样的操作。 

  3. sortArray:这是对外的接口方法,它首先初始化随机数种子,然后调用QuickSort方法对输入的数组nums进行排序,最后返回排序后的数组。

这段代码的主要优点是它使用了随机化的快速排序算法,可以在平均情况下达到O(n log n)的时间复杂度,而且它的空间复杂度为O(log n),因为它只需要递归调用栈的空间。

七、归并排序

class Solution {
public:
    void InsertSort(vector<int>& a, int begin, int end)
    {
        for(int i=begin+1; i<=end; i++)
        {
            int tmp=a[i];
            int j=i;
            while(j>begin && a[j-1]>tmp){
                a[j]=a[j-1];
                j--;
            }
            a[j]=tmp;
        }
    }
    void _MergeSort(vector<int>& a,int begin,int end,vector<int>& tmp)
    {
        if (begin >= end) {
            return;
        }
        if (end - begin + 1 < 10){
	    	InsertSort(a, begin, end);
	    	return;
	    }
        int mid=(begin+end)/2;
        _MergeSort(a,begin,mid,tmp);
        _MergeSort(a,mid+1,end,tmp);
        int begin1=begin,end1=mid;
        int begin2=mid+1,end2=end;
        int i=begin;
        while(begin1<=end1&&begin2<=end2)
        {
            if(a[begin1]<a[begin2])
                tmp[i++]=a[begin1++];
            else
                tmp[i++]=a[begin2++];
        }
        while(begin1<=end1)
            tmp[i++]=a[begin1++];
        while(begin2<=end2)
            tmp[i++]=a[begin2++];
        for (i = begin; i <= end; i++)
        {
            a[i] = tmp[i];
        }
    }
    vector<int> sortArray(vector<int>& nums)
    {
         vector<int> tmp(nums.size());
        _MergeSort(nums,0,nums.size()-1,tmp);
        return nums;
    }
};

八、计数排序

class Solution {
public:
    
    vector<int> sortArray(vector<int>& nums)
    {
        // 找到数组中的最大值和最小值
        int minVal = INT_MAX, maxVal = INT_MIN;
        for (int num : nums) {
            minVal = min(minVal, num);
            maxVal = max(maxVal, num);
        }
        
        // 统计每个元素出现的次数
        vector<int> count(maxVal - minVal + 1, 0);
        for (int num : nums) {
            count[num - minVal]++;
        }
        
        // 根据统计结果重新构造排序后的数组
        vector<int> sortedArray;
        for (int i = 0; i < count.size(); i++) {
            for (int j = 0; j < count[i]; j++) {
                sortedArray.push_back(i + minVal);
            }
        }
        
        return sortedArray;
    }
};
  • 当我们使用计数排序算法时,我们首先需要找到待排序数组中的最大值和最小值。这是为了确定计数数组的大小,以及后续构造排序后的数组时的索引范围。
  • 接下来,我们创建一个计数数组 count,其大小为 maxVal - minVal + 1,其中 maxVal 是数组中的最大值,minVal 是数组中的最小值。计数数组用于统计每个元素出现的次数。
  • 然后,我们遍历待排序数组 nums,对于每个元素 num,我们将其在计数数组中对应的位置的值加1,表示该元素出现了一次。
  • 接着,我们根据统计结果重新构造排序后的数组 sortedArray。我们从计数数组的第一个位置开始遍历,对于每个计数数组的索引 i,我们将其对应的值 count[i] 表示的元素值(即 i + minVal)按照出现次数依次添加到 sortedArray 中。
  • 最后,我们返回排序后的数组 sortedArray

计数排序算法的时间复杂度为 O(n+k),其中 n 是待排序数组的长度,k 是待排序元素的范围。由于计数排序是一种稳定的排序算法,它可以在线性时间内完成排序。

版权声明:本文为博主作者:Han同学原创文章,版权归属原作者,如果侵权,请联系我们删除!

原文链接:https://blog.csdn.net/m0_73800602/article/details/135032247

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
xiaoxingxing的头像xiaoxingxing管理团队
上一篇 2024年1月6日
下一篇 2024年1月6日

相关推荐