常用排序汇总

语法简单说明

using namespace std;
template <typename T>

插入排序InsertionSort

  • 查找出arr(i)在L[1…i-1]中的插入位置k
  • 将arr[k…i-1]中所有元素全部后移一个位置
  • 将arr(i)复制到arr(k)
void insertionSort( T arr[], int n){    //插入排序
    for(int i = 1; i < n; i++){    //插入排序从i= 1开始,因为第一个元素从一开始就已经有序了
        //寻找元素arr[i]合适的插入位置
//        for(int j = i; j>0; j--)  //循环到最后j=1,判断与j=0位置的元素是否交换,相对于选择排序,第二层循环会提前结束
//            if( arr[j] <  arr[j-1])
//                swap(arr[j], arr[j-1]);
//            else
//                break;
//或者采用下面的方法,将判断放在for循环中
//        for(int j = i; j>0&&arr[j] <arr[j-1];j--){
//            swap(arr[j],arr[j-1]);
//        }
        //经过优化后的代码
        T e = arr[i];
        int j;    //j保存元素e应该插入的位置
        for(j = i; j>0 && arr[j-1] > e; j--){
            arr[j] = arr[j-1];    //把j-1位置的元素向后挪一下
        }
        arr[j] = e;
    }
}
#插入排序Python版
def insertion_sort(a):
    for i in range(1,len(a)):
        cur = a[i]
        j = i
        while j>0 and a[j-1]>cur:
            a[j] = a[j-1]
            j -= 1
        a[j] = e
    return a

选择排序SelectionSort

版本一
void selectionSort( T arr[], int n){    //选择排序
    for(int i = 0; i < n; i++){
        //寻找[i, n)区间的最小值
        int minIndex = i;
        for( int j = i+1; j<n;j++)
            if(arr[j] < arr[minIndex])
                minIndex = j;
        swap( arr[i], arr[minIndex]);  // C++标准库
    }
}
版本二,优化

在每一轮中, 可以同时找到当前未处理元素的最大值和最小值

void selectionSort(T arr[], int n){

    int left = 0, right = n - 1;
    while(left < right){
        int minIndex = left;
        int maxIndex = right;
        // 在每一轮查找时, 要保证arr[minIndex] <= arr[maxIndex]
        if(arr[minIndex] > arr[maxIndex])
            swap(arr[minIndex], arr[maxIndex]);

        for(int i = left + 1 ; i < right; i ++)
            if(arr[i] < arr[minIndex])
                minIndex = i;
            else if(arr[i] > arr[maxIndex])
                maxIndex = i;

        swap(arr[left], arr[minIndex]);
        swap(arr[right], arr[maxIndex]);

        left ++;
        right --;
    }

    return;
}
#直接选择排序Python版
def selection_sort(a):
    for i in range(len(a)-1):
        min_index = i
        for j in range(i+1, len(a)):
            if a[j]<a[min_index]:
                min_index = j
        if i != min_index:
            a[i], a[min_index] = a[min_index], a[i]
    return a

希尔排序ShellSort

void shellSort(T arr[], int n){
     // 计算 increment sequence: 1, 4, 13, 40, 121, 364, 1093...
    int h = 1;
    while(h < n/3)
        h = 3 * h + 1;    //取一个步长

    while(h >= 1){
        for( int i = h; i <n ; i++){
            //对arr[i], arr[i-h], arrr[i-2*h], arr[i-3*h]...使用插入排序
            T e = arr[i];
            int j;
            for( j=i; j >= h&& e<arr[j-h]; j-=h)
                arr[j] = arr[j-h];     //从后往前寻找插入位置
            arr[j]=e;
        }
        h/=3;
    }
}

冒泡排序BubbleSort

版本一
void bubbleSort( T arr[] , int n){
    bool swapped;
    do{
        swapped = false;
        for( int i = 1 ; i < n ; i ++ )
            if( arr[i-1] > arr[i] ){
                swap( arr[i-1] , arr[i] );
                swapped = true;
            }
        // 优化, 每一趟Bubble Sort都将最大的元素放在了最后的位置
        // 所以下一次排序, 最后的元素可以不再考虑
        n --;
    }while(swapped);
}
版本二
// 我们的第二版bubbleSort,使用newn进行优化
template<typename T>
void bubbleSort2( T arr[] , int n){

    int newn; // 使用newn进行优化
    do{
        newn = 0;
        for( int i = 1 ; i < n ; i ++ )
            if( arr[i-1] > arr[i] ){
                swap( arr[i-1] , arr[i] );
                // 记录最后一次的交换位置,在此之后的元素在下一轮扫描中均不考虑
                newn = i;
            }
        n = newn;
    }while(newn > 0);
}
#冒泡排序
def bubble_sort(a, n):
    ac = a.copy()
    swap_size = 1
    while swap_size > 0:
        swap_size = 0
        for i in range(n-1):
            if ac[i] > ac[i+1]:
                ac[i], ac[i+1] = ac[i+1], ac[i]
                swap_size += 1
        n -= 1
    return ac

快速排序QuickSort

// 对arr[l...r]部分进行快速排序
template <typename T>
void __quickSort(T arr[], int l, int r){

    if( l >= r )
        return;
    int p = __partition(arr, l, r);
    __quickSort(arr, l, p-1 );
    __quickSort(arr, p+1, r);
}
版本一,双路
int __partition2(T arr[], int l, int r){    //双路快速排序

    swap(arr[l], arr[rand()%(r-l+1)+l]);
    T v = arr[l];

    //arr[l+1...i) <= v;  arr(j...r] >= v
    int i = l+1, j = r;
    while(true){
        while(i <=r && arr[i] <v) i++;
        while(j >= l+1 && arr[j] > v) j--;
        if( i> j) break;
        swap( arr[i], arr[j] );
        i++;
        j--;
    }
    swap(arr[l], arr[j]);
    return j;
}
版本二 ,三路
// 递归的三路快速排序算法
template <typename T>
void __quickSort3Ways(T arr[], int l, int r){

    // 对于小规模数组, 使用插入排序进行优化
    if( r - l <= 15 ){
        insertionSort(arr,l,r);
        return;
    }

    // 随机在arr[l...r]的范围中, 选择一个数值作为标定点pivot
    swap( arr[l], arr[rand()%(r-l+1)+l ] );

    T v = arr[l];

    int lt = l;     // arr[l+1...lt] < v
    int gt = r + 1; // arr[gt...r] > v
    int i = l+1;    // arr[lt+1...i) == v
    while( i < gt ){
        if( arr[i] < v ){
            swap( arr[i], arr[lt+1]);
            i ++;
            lt ++;
        }
        else if( arr[i] > v ){
            swap( arr[i], arr[gt-1]);
            gt --;
        }
        else{ // arr[i] == v
            i ++;
        }
    }

    swap( arr[l] , arr[lt] );

    __quickSort3Ways(arr, l, lt-1);
    __quickSort3Ways(arr, gt, r);
}

template <typename T>
void quickSort3Ways(T arr[], int n){

    srand(time(NULL));
    __quickSort3Ways( arr, 0, n-1);
}

合并排序MergeSort

void MergeSort(T A[], int low, int high){
    if(low < high){
        int mid = (low+high)/2;  //从中间划分两个子序列
        MergeSort(A, low, mid);  //对左侧子序列进行递归排序
        MergeSort(A, mid, high);
        Merge(A, low, mid, high); //归并
    }
}

void Mereg( T A[], int low, int mid, int high){
    //表A的两段A[low...mid]和A[mid+1...high]各自有序,将他们合成一个有序表
    T B[high-low+1];
    for (int k = low; k < high; ++k) 
        B[k] = A[k];
    for (int i=low, j=mid+1, k=i; i<=mid && j<=high ; k++) {
        if(B[i] <= B[j])
            A[k] = B[i++];
        else
            A[k] = B[j++];
    } //for
    
    while(i<=mid) A[k++] = A[i++];  //若左半部分未检测完,复制
    while(j<=high) A[k++] = A[j++];
}

堆排序

//创建一个大根堆
void BuildMaxHeap(T A[], int len){
    for (int i = len/2; i > 0; i--)
        AdjustDown(A, i, len);
}

void shiftUp(int k){               
    while( k>1 && data[k/2] < data[k]){   
        swap(data[k/2], data[k]);
        k /= 2;
    }
}

void AdjustDown(T A[], int k, int len){
    //将元素k向下调整
    T e = A[k];
    for (int i = 2*k; i <= len; i*=2) {
        if(i<len&&A[i]<A[i+1])
            i++;
        if(e>=A[i]) break;
        else{
            A[k] = A[i];
            k=i;
        }
    }
    A[k] = e;
}

void HeapSort(T A[], int len){
    BuildMaxHeap(A, len);     //初始建堆
    for (int i = len; i > 1 ; i--) {
        Swap(A[i], A[1]);    // 输出堆顶元素(和堆底元素进行交换)
        AdjustDown(A, 1, i-1);  //剩余i-1个元素整理成堆

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值