经典排序算法(升序,C++实现),常考的排序算法(快排,堆排,归并等)

  1. 冒泡排序
    相邻元素比较,每次“浮”出最大(最小) 平均时间复杂度: O(N^2)
    可以提前退出
    void bubbleSort(vector<int>&nums,int start , int end){
        for(int i = start ;i < end;++i){
            bool flag = false;
            for(int j = start ; j < end - 1 - i ; ++j){
                if(nums[j] > nums[j+1]){
                    swap(nums[j],nums[j+1]);
                    flag = true;
                }     
            }
            if(false == flag) {
                cout<< " 提前退出 "<<endl;
                return;
            }
        }
    }
  1. 选择排序
    每一轮从未排序的部分中选出最大(最小)的 平均时间复杂度:O(N^2)
   //选择排序  升序 
    void selectSort(vector<int>&nums,int start , int end){
        for(int i = start ;i < end ;++i){
            int index = start;
            //int maxN = INT_MIN;
            for(int j = start; j  < end - i ; ++j){
            //    if(nums[j] > maxN){
            //        maxN = nums[j];
            //        index = j;
            //    }
                if(nums[j] > nums[index]){
                    index = j;
                }
            }
            swap(nums[index],nums[end-1-i]);
        }
    }
  1. 插入排序
    将前面数据视为排好序的,将当前待插入的数据与前面排好顺序的数据进行比较,找到插入数据的位置,以此类推。 O(N^2)

    void insertionSort(vector<int>&nums,int start , int end){
        for(int i = start ;i < end ;++i){
           int tmp = nums[i];
           int j =  i-1;
           for(; j>= 0 && nums[j] > tmp;--j){
                nums[j+1] = nums[j];
           }
            nums[j+1] = tmp;
        }
    }
  1. 希尔排序
    将插入排序进行了优化,插入排序适合部分有顺序的数据,通常采用一个递减到1的序列数,调节步长将长序列拆分成多个,步长逐渐缩小,使数据大部分都有序的时候可以提高排序效率。
    平均时间复杂度:O(NlongN)~ O(N^2)
void shellSort(vector<int>& nums ,int start,int end){
    for(int kd = end/2;kd >= 1;kd = kd/2){
        for(int i = kd ;i < end; ++i){
            int tmp = nums[i],j;
            for(j = i - kd;j>= 0 && nums[j] > tmp;j = j -kd){
                nums[j+kd] = nums[j];
            }
            nums[j+kd] = tmp;
        }
    }
}
  1. 快速排序
    每次选取一个基数,将数组分成大于基数和小于基数的两个区间,不断再递归左右区间。
    平均时间复杂度:O(NlongN)
  // 区间左闭右闭
  int partition(vector<int>& nums,int start,int end){
          int pivot = nums[start];
         while(start<end) {
            while(start<end && nums[end]>=pivot)--end;
             nums[start] = nums[end];
             while(start<end && nums[start]<=pivot) ++start;
            nums[end] = nums[start];
         }
         nums[start] = pivot;
         return start;
     }
     void quickSort(vector<int>& nums ,int start,int end){
         if(start<end ) {
             int pivotpos = partition(nums,start,end);
             quickSort(nums,start,pivotpos-1);
             quickSort(nums,pivotpos+1,end);
         }
     }
//  优化快排
 void quickSort(vector<int>&nums, int left, int right){
        if(left >= right){
            return;
        }
        int pivot = partition(nums, left, right);
        int leftPivot = pivot - 1;
        int rightPivot = pivot + 1;
        //优化重复元素
        while(leftPivot > left && nums[leftPivot] == nums[pivot]){
            leftPivot --;
        }
        while(rightPivot < right && nums[rightPivot] == nums[pivot]){
            rightPivot++;
        }
        quickSort(nums, left, leftPivot);
        quickSort(nums, rightPivot, right);
    }

   int partition(vector<int>&nums, int left, int right){
        //随机化选取分隔符,降低递归树高度
        int randomIndex = left + (int)(rand() / double(RAND_MAX) * (right - left + 1));
        int tmp = nums[left];
        nums[left] = nums[randomIndex];
        nums[randomIndex] = tmp;
        int pivotVal = nums[left];
        while(left < right){
            while(left < right && nums[right] >= pivotVal){
                right --;
            }
            nums[left] = nums[right];
            while(left < right && nums[left] <= pivotVal){
                left ++;
            }
            nums[right] = nums[left];
        }
        nums[left] = pivotVal;
        return left;
    }
  1. 堆排序
    一般情况下升序排序使用最大堆,降序排序排序使用最小堆
    先构建大根堆,然后每次将堆顶和倒数第一个交换,调整,然后再交换对顶和倒数第二个
    平均时间复杂度:O(NlongN)

 //堆调整  
   void adjust(vector<int> &nums, int len, int index){
        int left = 2*index + 1; // index的左子节点
        int right = 2*index + 2;// index的右子节点

        int maxIdx = index;
        if(left<len && nums[left] > nums[maxIdx])     maxIdx = left;
        if(right<len && nums[right] > nums[maxIdx])     maxIdx = right;
 
        if(maxIdx != index)
        {
        swap(nums[maxIdx], nums[index]);
        adjust(nums, len, maxIdx);
        }
    }
 
    // 堆排序      
    void HeapSort(vector<int> &nums, int size){
       for(int i=size/2 - 1; i >= 0; i--){
            adjust(nums, size, i);
        }
         for(int i = size - 1; i >= 1; i--){
                swap(nums[0], nums[i]);        
                ad just(nums, i, 0);  // 调整除了排序好的部分,得到新的堆            
            }
        }
  1. 归并
    将区间拆分成两段或者多段,对小段区间进行排序,然后再对有序数组进行合并。
    平均时间复杂度:O(NlongN)
  // 归并排序
    void mergeSortInOrder(vector<int>&arr,int bgn,int mid, int end){
        int l = bgn, m = mid +1, e = end;
        vector<int> arrs(end - bgn + 1);
        int k = 0;
        while(l <= mid && m <= e){
            if(arr[l] < arr[m]){
                arrs[k++] = arr[l++];
            }else{
                arrs[k++] = arr[m++];
            }
        }
        while(l <= mid){
            arrs[k++] = arr[l++];
        }
        while(m <= e){
            arrs[k++] = arr[m++];
        }
        for(int i = 0; i < arrs.size(); i++){
            arr[i + bgn] = arrs[i];
        }
    }

    void mergeSort(vector<int>& arr, int bgn, int end)
    {
        if(bgn >= end){
            return;
        }
        int mid = (bgn + end) >> 1;
        mergeSort(arr,bgn,mid);
        mergeSort(arr,mid + 1, end);
        mergeSortInOrder(arr,bgn,mid,end);
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值