冒泡、选择、插入是基本,笔试快排经常考!
Talk is cheap, show you the code.
// #include <iostream>
// #include <vector>
// #include <algorithm>
// #include <cmath>
#include <bits/stdc++.h>
void bubbleSort(std::vector<int>& arr); // 1、冒泡排序
void selectSort(std::vector<int>& arr); // 2、选择排序
void insertSort(std::vector<int>& arr); // 3、插入排序
void shellSort(std::vector<int>& arr); // 4、希尔排序
void shellSort2(std::vector<int>& arr); // 假的希尔排序
void mergeSort(std::vector<int>& arr, int left, int right); // 5、归并排序
void quickSort(std::vector<int>& arr, int left, int right); // 6、快速排序
void quickSort2(std::vector<int>& arr, int left, int right); // 效率较低
void heapSort(std::vector<int>& arr); // 7、堆排序
void sink(std::vector<int>& arr, int index, int len); // 堆排序的 下沉操作
void countSort(std::vector<int>& arr); // 8、计数排序
void bucketSort(std::vector<int>& arr); // 9、桶排序
void radixSort(std::vector<int>& arr); // 10、基数排序
int main()
{
//产生 0-10000 的随机数组
std::vector<int> data(10000, 0);
srand((int)time(NULL));
for (int i = 0; i < 10000; ++i)
data[i] = rand() % 10000;
std::cout << "before sort ----- \n";
for(const int& d : data)
std::cout << d << '\t';
std::cout << "\n\n\n\n";
clock_t start, end;
start = clock(); //计时开始
bucketSort(data);
end = clock(); //计时结束
std::cout << "after sort ----- \n";
for(const int& d : data)
std::cout << d << '\t';
std::cout << "\n\n\n\n";
std::cout << "sort time ----- " << float((end - start) * 1000 / CLOCKS_PER_SEC) << "ms\n\n\n";
system("pause");
}
// ***** 冒泡排序 ***** //
// 时间复杂度:O(n2) 空间复杂度:O(1) 稳定排序
void bubbleSort(std::vector<int>& arr)
{
int len = arr.size();
for (int i = len - 1; i > 0; --i) //循环(len-1)次
{
for (int j = 0; j < i; ++j) //不断将大数交换到最后
{
if(arr[j] > arr[j + 1])
{
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
// ***** 选择排序 ***** //
// 时间复杂度:O(n2) 空间复杂度:O(1) 非稳定排序
void selectSort(std::vector<int>& arr)
{
int len = arr.size();
for (int i = 0; i < len; ++i) //循环(len-1)次
{
int index = i;
for (int j = i + 1; j < len; ++j) //每次找出最小的数并放到前面
{
if(arr[index] > arr[j])
index = j;
}
int tmp = arr[index];
arr[index] = arr[i];
arr[i] = tmp;
}
}
// ***** 插入排序 ***** //
// 时间复杂度:O(n2) 空间复杂度:O(1) 稳定排序
void insertSort(std::vector<int>& arr)
{
int len = arr.size();
for (int i = 1, j; i < len; ++i) //循环(len-1)次
{
int curValue = arr[i];
for (j = i - 1; j >= 0; --j) //往前遍历
{
if(curValue < arr[j])
arr[j + 1] = arr[j]; //后移
else
break;
}
arr[j + 1] = curValue; //插入
}
}
// ***** 希尔排序 ***** //
// 时间复杂度:O(nlogn) 空间复杂度:O(1) 非稳定排序
void shellSort(std::vector<int>& arr)
{
int len = arr.size();
int gap = len / 2;
while(gap > 0)
{
for (int i = gap, j; i < len; ++i) //插入排序的升级版
{
int cur = arr[i];
for (j = i - gap; j >= 0; j -= gap) //往前遍历
{
if(arr[j] > cur)
arr[j + gap] = arr[j]; //后移
else
break;
}
arr[j + gap] = cur; //插入
}
gap /= 2;
}
}
void shellSort2(std::vector<int>& arr)
{
int len = arr.size();
for (int i = len / 2; i > 0; --i)
{
for (int j = i; j < len; ++j)
{
int k = j - i;
while(k >= 0 && arr[k] < arr[j])
k -= i;
if(k >= 0)
{
int tmp = arr[j];
arr[j] = arr[k];
arr[k] = tmp;
}
}
}
}
// ***** 归并排序 ***** //
// 时间复杂度:O(nlogn) 空间复杂度:O(n) 稳定排序
void mergeSort(std::vector<int>& arr, int left, int right)
{
// 终止条件,不治而治
if(left >= right)
return;
// 分而治之
int mid = left + (right - left) / 2;
mergeSort(arr, left, mid);
mergeSort(arr, mid + 1, right);
// 合并
std::vector<int> tmp(arr);
int i = left, j = mid + 1;
for (int k = left; k <= right; ++k)
{
if(j > right || (i <= mid && tmp[i] < tmp[j]))
arr[k] = tmp[i++];
else
arr[k] = tmp[j++];
}
}
// ***** 快速排序 ***** //
// 时间复杂度:O(nlogn) 空间复杂度:O(logn) 非稳定排序
void quickSort(std::vector<int>& arr, int left, int right)
{
// 终止条件
if(left >= right)
return;
// arr[left] 作为基准
int i = left + 1; // i在左边,用于找出 大于 基准的数
int j = right; // j在右边,用于找出 小于 基准的数
while (true)
{
while(i <= j && arr[i] <= arr[left]) //找到 大于基础的数,停下来,待会移到右边
++i;
while(i <= j && arr[j] >= arr[left]) //找到 小于基础的数,停下来,待会移到左边
--j;
// 交换找到的左右两数
if(i < j)
{
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
else
{
break;
}
}
// 插入基准数
int tmp = arr[left];
arr[left] = arr[j];
arr[j] = tmp;
quickSort(arr, left, j - 1);
quickSort(arr, j + 1, right);
}
void quickSort2(std::vector<int>& arr, int left, int right)
{
if(left >= right)
return;
int i, j;
for (i = left, j = left; j < right; ++j)
{
if(arr[j] < arr[right]) //以最右边为基准数
{
// 小于基准数则放到左边
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
++i;
}
}
// 插入基准数
int tmp = arr[i];
arr[i] = arr[right];
arr[right] = tmp;
quickSort2(arr, left, i - 1);
quickSort2(arr, i + 1, right);
}
// ***** 堆排序 ***** //
// 时间复杂度:O(nlogn) 空间复杂度:O(1) 非稳定排序
void heapSort(std::vector<int>& arr)
{
int len = arr.size();
// 调整数组为堆
for (int i = (len - 2) / 2; i >= 0; --i)
sink(arr, i, len);
// 交换头尾,并执行下沉操作
for (int i = len - 1; i > 0; --i)
{
int tmp = arr[0];
arr[0] = arr[i];
arr[i] = tmp;
sink(arr, 0, i);
}
}
void sink(std::vector<int>& arr, int index, int len)
{
int curVal = arr[index];
int childIndex = 2 * index + 1;
while (childIndex < len)
{
//大顶堆,对应升序排
int maxIndex = childIndex;
if(childIndex + 1 < len && arr[childIndex + 1] > arr[childIndex])
maxIndex = childIndex + 1;
if(arr[maxIndex] <= curVal)
break;
arr[index] = arr[maxIndex];
index = maxIndex;
childIndex = index * 2 + 1;
}
arr[index] = curVal;
}
// ***** 计数排序 ***** //
// 时间复杂度:O(n+k) 空间复杂度:O(k) 稳定排序
void countSort(std::vector<int>& arr)
{
// 找到最大最小值
int minVal = arr[0], maxVal = arr[0];
for (const int& a : arr)
{
if(a < minVal)
minVal = a;
if(a > maxVal)
maxVal = a;
}
// 建立临时数组,统计每个值出现的次数
std::vector<int> countArr(maxVal - minVal + 1, 0);
for(const int& a : arr)
++countArr[a - minVal];
// 将临时数组拷贝回原数组
for (int i = 0, index = 0; i < countArr.size(); ++i)
{
for (int j = 0; j < countArr[i]; ++j)
{
arr[index] = i + minVal;
++index;
}
}
}
// ***** 桶排序 ***** //
// 时间复杂度:O(n+k) 空间复杂度:O(n+k) 稳定排序
void bucketSort(std::vector<int>& arr)
{
// 找到最大最小值
int minVal = arr[0], maxVal = arr[0];
for (const int& a : arr)
{
if(a < minVal)
minVal = a;
if(a > maxVal)
maxVal = a;
}
//求差值创建桶,默认桶区间大小为5,遍历数组将每个元素存入对应的桶
int dValue = maxVal - minVal;
int bucketNum = dValue / 5 + 1;
std::vector<std::vector<int>> bucketVec(bucketNum, std::vector<int>());
for (int i = 0; i < arr.size(); ++i)
{
int index = (arr[i] - minVal) * (bucketNum - 1) / dValue;
bucketVec[index].emplace_back(arr[i]);
}
//对桶内元素排序
for (int i = 0; i < bucketNum; ++i)
std::sort(bucketVec[i].begin(), bucketVec[i].end());
//把桶内元素汇总到原数组
int index = 0;
for (int i = 0; i < bucketNum; ++i)
{
for (int j = 0; j < bucketVec[i].size(); ++j)
{
arr[index] = bucketVec[i][j];
++index;
}
}
}
// ***** 基数排序 ***** //
// 时间复杂度:O(kn) 空间复杂度:O(n+k) 稳定排序
void radixSort(std::vector<int>& arr)
{
//找最大值
int max = arr[0];
for (int i = 1; i < arr.size(); ++i)
{
if(max < arr[i])
max = arr[i];
}
//计算最大值是几位
int num = 1;
while(max / 10 > 0)
{
++num;
max /= 10;
}
//创建10个桶,从个位数开始排序
std::vector<std::vector<int>> bucketVec(10, std::vector<int>());
for (int i = 0; i < num; ++i)
{
//存入对应桶
for (int j = 0; j < arr.size(); ++j)
{
int index = arr[j] / (int)pow(10, i) % 10;
bucketVec[index].emplace_back(arr[j]);
}
//放回原数组
int index = 0;
for (int i = 0; i < 10; ++i)
{
for (int j = 0; j < bucketVec[i].size(); ++j)
{
arr[index] = bucketVec[i][j];
++index;
}
bucketVec[i].clear(); //清空以备下次使用
}
}
}