0
点赞
收藏
分享

微信扫一扫

C++编程:常用排序算法

快乐小码农 2022-02-23 阅读 102

C++编程:常用排序算法

冒泡排序

算法思想:

  1. 比较相邻的元素。如果第一个比第二个大,就交换它们两个;
  2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;
  3. 针对所有的元素重复以上的步骤,除了最后一个;
  4. 重复步骤1~3,直到排序完成。
void mySort(vector<int>& nums){
    if(nums.size()<2){
        return;
    }
    for(int i = 0; i<nums.size()-1; i++){
        for(int j = 0; j<nums.size()-1-i; j++){
            if(nums[j] > nums[j+1]){ //升序 (降序的话换成<即可)
                swap(nums[j], nums[j+1]);
            }
        }
    }
}

选择排序

算法思想:
选择排序(Selection-sort)是一种简单直观的排序算法。它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

//下面有问题但是还没有排查出来
void mySort(vector<int>& nums){
    if(nums.size()<2){
        return;
    }
    int minNum;//这里用下标,直接保存数值的话会出错
    int tmp;
    for(int i=0; i<nums.size()-1;i++){ //注意i不取最后一个,因为j是i后面的
        minNum = i;
        for(int j=i+1; j<nums.size();j++){
            if(nums[j] < nums[minNum]){
                minNum = j;
            }
        }
        swap(nums[minNum], nums[i]);
    }
}

插入排序

算法思想:
通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。一般认为第一个数据是有序的。

void mySort(vector<int>& nums){
    if(nums.size()<2){
        return;
    }
    int preIndex;//记录有序数组的最后一个下标
    int current;
    for(int i=1; i<nums.size();i++){
        preIndex = i-1;
        current = nums[i];
        while(preIndex>=0 && nums[preIndex]>current){
            nums[preIndex+1] = nums[preIndex];
            preIndex--;
        }
        nums[preIndex+1]=current;
    }
}

希尔排序

算法思想:
第一个突破O(n2)的排序算法,是简单插入排序的改进版。它与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序又叫缩小增量排序。

//时间原因,还没有看懂呢
void mySort(vector<int>& nums){
    if(nums.size()<2){
        return;
    }
    for(int gap=nums.size()/2; gap>0; gap=gap/2){
        for(int i=gap; i<nums.size(); i++){
            int j = i;
            int current = nums[i];
            while(j-gap>=0 && current<nums[j-gap]){
                nums[j] = nums[j-gap];
                j = j-gap;
            }
            nums[j] = current;
        }
    }
}

归并排序

算法思想:
该算法是采用分治法(Divide and Conquer)的一个非常典型的应用,速度仅次于快速排序。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。

//使用了tmp保存结果
void mySort(vector<int>& nums,int begin,int end,vector<int>& tmp){
    if(begin == end){
        return;
    }
    int mid = (begin+end)/2;
    mySort(nums, begin, mid, tmp);
    mySort(nums, mid+1, end, tmp);
    
    int i = begin;
    int j = mid+1;
    int s = begin;//s指向临时结果数组
    
    // 比较两个有序小数组的元素,依次放入大数组中
    while (i <= mid && j <= end) {
        if(nums[i] < nums[j]){
            tmp[s++] = nums[i++];
        }
        else{
            tmp[s++] = nums[j++];
        }
    }
    // 右侧小数组已排序完毕,左侧小数组还有剩余,将左侧小数组元素依次放入大数组尾部
    while (i <= mid) {
        tmp[s++] = nums[i++];
    }
    // 左侧小数组已排序完毕,右侧小数组还有剩余,将右侧小数组元素依次放入大数组尾部
    while (j <= end) {
        tmp[s++] = nums[j++];
    }
}

快速排序

//快速排序
void func(vector<int>& nums,int begin,int end){
    if(begin < end){
        int tmp = nums[begin];//选择基准,一般选择第一个作为基准
        int i = begin;
        int j = end;//j指向最右边的元素
        
        while (i < j) {
            //nums[j]小于tmp的话才需要移动
            while (i<j && nums[j] >= tmp) {
                j--;
            }
            nums[i] = nums[j];
            //nums[i]大于tmp的话才需要移动
            while (i<j && nums[i] <= tmp) {
                i++;
            }
            nums[j] = nums[i];
        }
        nums[i] = tmp;
        func(nums,begin,i-1);
        func(nums,i+1,end);
    }
}

快速排序算法参考

归并排序算法参考

十大排序算法参考

举报

相关推荐

0 条评论