排序の总结

排序总结

1.冒泡排序

时间复杂度:n^2,空间复杂度:O(1),稳定。冒泡这个名字十分形象,排序过程中通过将相邻两个元素进行调换,达成把最大值(或最小值)换到末尾

for (int i = 0;i < n - 1;i ++){

for (int j = 0;j < n - 1 - i;j ++){
	if (a[j] > a[j + 1]){
		swap(a[j],a[j + 1]);
	}
   }

}

2.快排(真的是太快辣)

时间复杂度:nlogn,空间复杂度:log n,不稳定。俗称交换排序。

void QuickSort(T *q, const int left, const int right) { if(left<right) { int i=left, j=right; int temp = q[left]; while(i<j) { while(q[j]>=temp && i<j) { j--; } while(q[i]<=temp && i<j) { i++; } swap(q[i],q[j]); } swap(q[left], q[j]); QuickSort(q, left, j-1); QuickSort(q, j+1, right); } }

3.插入排序

时间复杂度:n^2,空间复杂度:o(1),稳定。把每一个插到正确位置上。

void insertArray(short * pArray, short count) {

short temp;
short pos;

for (int i = 1; i < count; i ++) {
    temp = pArray[i];
    pos = i - 1;
    while (temp < pArray[pos]) {
        pArray[pos + 1] = pArray[pos];
        pos--;
    }
    pArray[pos + 1] = temp;
}

}

4.希尔排序

时间复杂度:nlogn,空间复杂度:O(1),不稳定主要思想是: 先将整个记录, 通过间隔分成若干个子序列, 分别进行插入排序, 待整个序列基本有序时, 再进行一次插入排序.

 void shell_sort(int parr[], int len) { int j; int tempval; int jump = len >> 1; //jump为数组长度一半的大小 while (jump != 0) //循环插入 { for (int i = jump; i < len; ++i) { tempval = parr[i]; j = i - jump; while (j >= 0 && tempval < parr[j]) { parr[j + jump] = parr[j]; j = j - jump; } parr[j + jump] = tempval; } jump >>= 1; //jump除等于2 } }

5.选择排序

时间复杂度:n^2,空间复杂度:O(1),不稳定。在队列中找到最小元素放到已排序列最后。

void selectArray(short * pArray, short count) {

short temp; //存储每次选择元素的数值
short k; //存储所选择元素的小标

for (short i = 0; i < count; i ++) {
    temp = pArray[i];
    k = i;
    for (short j = i; j < count; j ++) {
        if (temp > pArray[j]) {
            temp = pArray[j];
            k = j;
        }
    }
    pArray[k] = pArray[i];
    pArray[i] = temp;
}

}

6.堆排序

时间复杂度nlogn 空间复杂度O(1),不稳定

 void HeapSort(int a[],int length) { int temp; BuildMaxHeap(a,length); for (int i = length - 1; i >= 1; i--) { //交换根节点和数组的最后一个节点 temp = a[i]; a[i] = a[0]; a[0] = temp; MaxHeapify(a, 0, 0, i-1);//维护从下标为i-1到0的子数组 } }

7.归并排序

时间复杂度nlogn,空间复杂度 O n+logn,稳定

 public static void mergeAB(int [] arrA,int [] arrB,int [] arrC){ //循环遍历两个需要归并的数组 for(int a=0,b=0,c=0;c<(arrA.length+arrB.length);){ //判断两个数组是否对应遍历完成 if(a==arrA.length){ //遍历完成A数组,则对应B中的元素只需要直接复制到C数组中 arrC[c++] = arrB[b++]; continue; } if(b==arrB.length){ arrC[c++] = arrA[a++]; continue; } //如果两个数组都没有遍历完,则进行比较操作 arrC[c++] = arrA[a]<arrB[b]?arrA[a++]:arrB[b++];

}
}

8.计数排序

时间复杂度 kn,空间复杂度 n+k,稳定计数排序是一种非比较排序算法,它用于排序的数的范围较小,例如在0到100之间。计数排序的基本思想是,统计数组中每个元素出现的次数,然后根据出现次数将元素排序。

 void countingSort(int arr[], int n) { int maxVal = arr[0]; for (int i = 1; i < n; i++) { if (arr[i] > maxVal) { maxVal = arr[i]; } } int count[maxVal+1], output[n]; memset(count, 0, sizeof(count)); for (int i = 0; i < n; i++) { count[arr[i]]++; } for (int i = 1; i <= maxVal; i++) { count[i] += count[i-1]; } for (int i = n-1; i >= 0; i--) { output[count[arr[i]]-1] = arr[i]; count[arr[i]]--; } for (int i = 0; i < n; i++) { arr[i] = output[i]; } }

9.桶排序

时间复杂度 n+k,空间复杂度 O(k),稳定桶排序将输入数据的区间均匀分成若干份,每一份称作“桶”。分别对每一个桶的内容进行排序,再按桶的顺序输出则完成排序。

 void Insert(vector & bkt, double num) { for (vector::iterator p = bkt.begin(); p != bkt.end(); ++p) if (*p > num) { bkt.insert(p, num); return ; } bkt.push_back(num); //没有找到,就放最后 }

void BucketSort(double * const begin, double * const end) { //假设输入数据都是小数[0,1) int n = end - begin; int i; vector<vector*> bucket(n); //为什么是n个桶,应该和hash一个原理

for (i = 0; i < n; ++i)
    bucket[i] = new vector<double>;
for (i = 0; i < n; ++i) { //按顺序插入到桶中
    Insert(*bucket[static_cast<int>(*(begin + i) * n)], *(begin + i));
}
int j = 0, k = 0;
for (i = 0; i < n; ++i) {
    while (k >= bucket[j]->size()) { //如果出现连续的空桶
        ++j;
        k = 0;
    }
    *(begin + i) = (*bucket[j])[k++];
}
for (i = 0; i < n; ++i)
    delete bucket[i];

}

10.基数排序

时间复杂度 n+k,空间复杂度O(n+k),稳定基数排序是一种思想很值得学习的排序方法。
它突破了正常的排序思维:先排高位,如果高位相同再排次高位,直至最低。它的思想是利用稳定排序从低位开始排,最后再排最高位。
另外它用来划分的位不一定是一位一位的划分,还可以是每几位一组,然后按组从低到高来排序。
事实上,当总位数b等于O(lgn),并且每一组的位数r等于logn时,基数排序的时间复杂度为θ(n)。

 int PickDigitOn_i(int n, const int i) { for (int k = 1; k <= i; ++k) n /= 10; return n % 10; }

void stablesort_onDigit_i(int * const begin, int * const end, int d) { //使用计数排序作为稳定排序 int temp[10] = {0}; //十进制数 vector out(end - begin);

for (int i = 0; i < end - begin; ++i)
    ++temp[PickDigitOn_i(*(begin + i), d)];
for (int i = 1; i < 10; ++i)
    temp[i] += temp[i-1];
for (int i = end - begin - 1; i >= 0; --i) {
    out[temp[PickDigitOn_i(*(begin + i), d)] - 1] = *(begin + i);
    --temp[PickDigitOn_i(*(begin + i), d)];
}
for (int i = 0; i < end - begin; ++i)
    *(begin + i) = out[i];

}

void RadixSort(int * const begin, int * const end) { //假设三位数的排序 for (int i = 0; i < 3; ++i) { stablesort_onDigit_i(begin, end, i); } }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值