排序算法总结

冒泡排序
/**
 * 冒泡排序
 * 最坏时间复杂度:O(n^2)
 * 平均时间复杂度:O(n^2)
 * 空间复杂度:O(1)
 * 算法稳定度:稳定
 */
template<class T>
void bubbleSort(T* start, T* end){
    if(start >= end) return;
    for(T* i = start; i != end; i++){
        for(int j = 0; j <= int(end-i)-1; j++){
            if(start[j] > start[j+1]) swap(start[j], start[j+1]);
        }
    }
}
选择排序
/**
 * 选择排序
 * 最坏时间复杂度:O(n^2)
 * 平均时间复杂度:O(n^2)
 * 空间复杂度:O(1)
 * 算法稳定度:不稳定
 */
template<class T>
void selectSort(T* start, T* end){
    if(start >= end) return;
    for(T* i = start; i != end; i++){
        int index = int(i-start);
        for(int j = int(i-start); j <= int(end-i); j++){
            if(start[j] > start[index]) index = j;
        }
        if(index != int(i-start)) swap(start[index], start[int(i-start)]);
    }
}
插入排序
/**
 * 插入排序
 * 最坏时间复杂的:O(n^2)
 * 平均时间复杂度:O(n^2)
 * 空间复杂度:O(1)
 * 算法稳定度:稳定
 */
template<class T>
void insertSort(T* start, T* end){
    for(int i = 1; i <= int(end-start); i++){
        int value = start[i], j = i;
        for(; j-1 >= 0 && value < start[j-1]; j--){
            start[j] = start[j-1];
        }
        start[j] = value;
    }
}
归并排序

/**
 * 归并排序
 * 最坏时间复杂度:O(nlogn)
 * 平均时间复杂度:O(nlogn)
 * 算法稳定性:稳定
 */
template<class T>
void mergeSort(T* start, T* end, T* tmp){
    if(start < end -1){
        int mid = int(end - start) / 2;
        int left = 0;
        int right = mid+1;
        int index = 0;
        mergeSort(start, start+mid, tmp);
        mergeSort(start+mid+1, end, tmp);
        while(left <= mid && right <= int(end-start)){
            if(start[left] <= start[right]) tmp[index++] = start[left++];
            else tmp[index++] = start[right++];
        }
        while(left <= mid){
            tmp[index++] = start[left++];
        }
        while(right <= int(end-start)){
            tmp[index++] = start[right++];
        }
        for(int i = 0; i < index; i++){
            start[i] = tmp[i];
        }
    }else if(start == end-1){
        if(start[0] > start[1]) swap(start[0], start[1]);
    }
}
希尔排序
/*
 * 希尔排序
 * 最坏时间复杂度:
 * 不稳定
 */
template<class T>
void shellSort(T* start, T* end){
    for(int i = int(end-start)/2; i >= 1; i/=2){
        for(int j = i; j <= int(end-start); j++){
            int value = start[j], k = j;
            for(; k-i >= 0 && start[k-i] > value; k-=i){
                start[k] = start[k-i];
            }
            start[k] = value;
        }
    }
}
堆排序
/*
 * 堆排序
 * 时间复杂度:nlogn
 * 稳定性:稳定
 */
template<class T>
void MaxHeapify(int curr, T* array, int size){
    if(curr >= size) return;
    int lchild = curr*2+1; //左右子树
    int rchild = lchild+1;
    while(rchild < size){
        //如果比左右子树都小的话,完成整理
        if(array[curr] >= array[lchild] && array[curr] >= array[rchild])
            return;
        if(array[lchild] > array[rchild]){//左子树比较大
            swap(array[lchild], array[curr]);
            curr = lchild;
        }else{
            swap(array[rchild], array[curr]);//右子树比较大
            curr = rchild;
        }
        lchild = curr*2+1;
        rchild = lchild+1;
    }
    //最后一个元素只有左子树的情况
    if(lchild < size && array[curr] < array[lchild]) swap(array[curr], array[lchild]);
}

template<class T>
void heapSort(T* array, int size){
    if(size < 1) return;
    for(int i = size-1; i >= 0; i--)
        MaxHeapify(i, array, size);
    while(size > 1){
        swap(array[0], array[size-1]);
        MaxHeapify(0, array, --size);
    }
}
快速排序
/**
 * 快速排序
 * 时间复杂度:nlogn
 * 稳定性:不稳定
 */
template<class T>
T getP(T* start, T* end){
    int mid = int(end-start)/2;
    int left = 0, right = int(end-start);
    if(start[left] > start[mid]) swap(start[left], start[mid]);
    if(start[left] > start[right]) swap(start[left], start[right]);
    if(start[mid] > start[right]) swap(start[mid], start[right]);
    return start[mid];
}

template<class T>
void quickSort(T* start, T* end){
    if(start <= end-2){
        int left = 1, right = int(end-start)-2;
        int mid = int(end-start)/2;
        int p = getP(start, end);
        swap(start[mid], start[int(end-start)-1]);
        while(1){
            //无需在循环中检测越界
            while(start[left] < p){left++;}
            while(start[right] > p){right--;}
            if(left < right) swap(start[left], start[right]);
            else break;
        }
        //为什么结束后和left坐标的值交换呢,是因为循环结束后,left处的值肯定大于p,
        //而且left左边的肯定小于p,右边的肯定大于p
        swap(start[left], start[int(end-start)-1]);
        quickSort(start, start+left-1);
        quickSort(start+left+1, end);
    }else
        getP(start, end);
}
计数排序
/*
 * 计数排序 (空间换时间)
 * 时间复杂度:O(n)
 */
template<class T>
void countingSort(T* array, int length){
    //找到最大的值
    int max = 0;
    for(int i = 0; i < length; i++)
        max = (max < array[i]) ? array[i] : max;
    //开辟空间并初始化
    T* indexs = new T[max+1];
    for(int i = 0; i < max+1; i++)
        indexs[i] = 0;
    //把待排序的数装入桶
    for(int i = 0; i < length; i++)
        indexs[array[i]]++;
    //对桶进行标号
    for(int i = 1; i < max+1; i++)
        indexs[i] += indexs[i-1];
    //倒出结果
    T result[length];
    for(int i = 0; i < length; i++){
        result[--indexs[array[i]]] = array[i];
    }
    for(int i = 0; i < length; i++)
        array[i] = result[i];
}
基数排序
/*
 * 基数排序
 * 时间复杂度:d(n+r)
 */
template<class T>
void radixSort(T* array, int length){
    T tmp[length];
    //找到所有数字中最大位数的数
    int max = 0;
    for(int i = 0; i < length; i++){
        int number = array[i];
        if(number < 0) number*=-1;
        max = (max < number) ? number : max;
    }
    //计算多少位
    int indexs = 0;
    if(max == 0) indexs = 1;
    else
        while(max){
            max /= 10;
            indexs++;
        }
    for(int j = 0; j < indexs; j++){
        vector<T> buck[20]; //桶 要考虑负数的情况
        int bit = 10;
        for(int k = 0; k < j; k++) bit*=10;
        //按照位数进行装桶
        for(int i = length-1; i >= 0; i--){
            int number = 0;
            //j位的数求j位的时候
            if(!(array[i]/bit) && (array[i]/(bit/10))) number = array[i]/(bit/10);
            else{
                number = array[i] - (array[i]/bit * bit);
                if(j != 0) number = number / (bit/10);//去掉第一位的情况
            }
            number+=9; //统统加9,这样就能包括负数的情况了
            buck[number].push_back(array[i]);
        }
        //将各位排好序的数按顺序倒出来
        int index = length-1;
        for(int i = 19; i >= 0; i--)
            for(int m = 0; m < buck[i].size(); m++)
                array[index--] = buck[i][m];
    }
}
经典例题
对一个序列排序,并求得排序后两数间最大差值

应用桶排序思想,找到最大数和最小数,
然后n个数,给定n个桶,第一个桶的范围是[min, min+(max-min)/n]
然后往下依次是[min+(max-min)/n*i, min+(max-min)/n*(i+1)]
最后一个的是范围是[min+(max-min)/n*(n-1), max],
这样正好把所有的数都包括进来,每个桶内的数差值肯定小于
两个桶之间数的差值,我们找前一个桶的最大值和后一个桶的最小值
来比较,这样就能求得排序后最大的差值

int shortestSubsequence(vector<int> rect, int n){
    if(n < 2) return 0;
    double min = rect[0], max = rect[0];
    for(int i = 0; i < int(rect.size()); i++){
        min = min > rect[i] ? rect[i] : min;
        max = max < rect[i] ? rect[i] : max;
    }
    //初始化桶
    vector<vector<int> > buck;
    for(int i = 0; i < n+1; i++){
        vector<int> v;
        buck.push_back(v);
    }
    double value = (max-min)/n;
    for(int i = 0; i < n; i++){//装桶
        for(int j = 0; j < n; j++){//遍历桶,合适就装进去
            double left = double(min + value*double(j));
            double right = double(min + value*double(j+1));
            if(double(rect[i]) >= left && double(rect[i]) <= right){
                buck[j].push_back(rect[i]);
                break;
            }
        }
    }
    //找最大差值
    min = -1, max = -1;
    int result = 0;
    for(int i = 0; i < n+1; i++){
        if(max != -1){
            for(int k = 0; k < buck[i].size(); k++){
                if(min == -1) min = buck[i][k];
                else min = buck[i][k] < min ? buck[i][k] : min;
            }
        }
        if(min != -1 && max != -1) {
            result = min-max > result ? min-max : result;
            max = min = -1;
        }
        if(max == -1){
            for(int k = 0; k < buck[i].size(); k++){
                if(max == -1) max = buck[i][k];
                else max = buck[i][k] > max ? buck[i][k] : max;
            }
        }
    }
    return result;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值