背景
网上很多排序算法运行结果是错误的,本小白很苦恼,因此花了一些时间汇总了各个算法,并给出main函数调用方式,本文仅为了分享个人学习记录,如有错误,欢迎讨论!
本文的代码均已在Visual Studio测试过,可放心ctrl C!具体每种算法的介绍与展开,后续有时间进行补充!
1.冒泡排序
void bubbleSort(int Array[], int ArraySize) {
for (int i = 0; i < ArraySize - 1; i++) {
for (int j = 0; j < ArraySize - 1 - i; j++) {
if (Array[j] > Array[j + 1]) {
int Temp = Array[j];
Array[j] = Array[j + 1];
Array[j + 1] = Temp;
}
}
}
}
1.1.冒泡排序优化版
void bubbleSortAdvanced(int Array[], int ArraySize) {
bool SwapFlag = false;
for (int i = 0; i < ArraySize - 1; i++) {
SwapFlag = false;
for (int j = 0; j < ArraySize - 1 - i; j++) {
if (Array[j] > Array[j + 1]) {
swap(Array[j], Array[j + 1]);
SwapFlag = true;
}
}
if (SwapFlag == false)
break;
}
}
2.选择排序
void selectSort(int Array[], int ArraySize) {
for (int i = 0; i < ArraySize - 1; i++) {
int Index = i;
for (int j = i + 1; j < ArraySize; j++) {
if (Array[j] < Array[Index])
Index = j;
}
swap(Array[Index], Array[i]);
}
}
3.插入排序
void insertSort(int Array[], int ArraySize) {
for (int i = 1; i < ArraySize; i++) {
for (int j = i; j > 0; j--) {
if (Array[j - 1] > Array[j])
swap(Array[j - 1], Array[j]);
else
break;
}
}
}
4.快速排序
void quickSort(int Array[], int ArraySize, int Left, int Right) {
if (Left >= Right) return;
int i = Left, j = Right, Base = Array[Left];
while (i < j) {
while (Array[j] >= Base && i < j)
j--;
while (Array[i] <= Base && i < j)
i++;
if (i < j)
swap(Array[i], Array[j]);
}
Array[Left] = Array[i];
Array[i] = Base;
quickSort(Array, ArraySize, Left, i - 1);
quickSort(Array, ArraySize, i + 1, Right);
}
5.希尔排序
void shellSort(int Array[], int ArraySize) {
for (int i = 0; i < ArraySize; i++) {
for (int j = i - 1; j >= 0 && Array[j + 1] < Array[j]; j--) {
swap(Array[j], Array[j + 1]);
}
}
}
6.归并排序
void mergeArray(int Array[], int ArraySize, int Left, int Middle, int Right) {
int LeftSize = Middle - Left + 1, RightSize = Right - Middle;
// 创建临时数组来保存左右两部分的数据
vector<int> LeftTempArray(LeftSize), RightTempArray(RightSize);
// 将数据复制到临时数组中
for (int i = 0; i < LeftSize; ++i)
LeftTempArray[i] = Array[Left + i];
for (int j = 0; j < RightSize; ++j)
RightTempArray[j] = Array[Middle + 1 + j];
// 将临时数组中的数据按顺序合并到原始数组中
int i = 0, j = 0, k = Left;
while (i < LeftSize && j < RightSize) {
if (LeftTempArray[i] <= RightTempArray[j]) {
Array[k] = LeftTempArray[i];
i++;
}
else {
Array[k] = RightTempArray[j];
j++;
}
k++;
}
// 将剩余的元素复制到原始数组中
while (i < LeftSize) {
Array[k] = LeftTempArray[i];
i++;
k++;
}
while (j < RightSize) {
Array[k] = RightTempArray[j];
j++;
k++;
}
}
static void mergeSort(int Array[], int ArraySize, int Left, int Right) {
if (Left >= Right)
return;
int Middle = Left + ((Right - Left) / 2);
mergeSort(Array, ArraySize, Left, Middle);
mergeSort(Array, ArraySize, Middle + 1, Right);
mergeArray(Array, ArraySize, Left, Middle, Right);
}
7.堆排序
void heapSort_MaxTree(int Array[], int StartIndex, int EndIndex) {
int ParentIndex = StartIndex; /* 父节点 */
int ChildIndex = 2 * StartIndex + 1; /* 子节点 */
while (ChildIndex < EndIndex) {
// 判断挑出 大的子节点 与 父节点 比较
if (ChildIndex + 1 < EndIndex && Array[ChildIndex] < Array[ChildIndex + 1])
ChildIndex++;
// 若父节点>子节点,则调整完毕.否则继续调整
if (Array[ParentIndex] > Array[ChildIndex])
return;
else {
// 交换父 子节点
swap(Array[ParentIndex], Array[ChildIndex]);
ParentIndex = ChildIndex;
ChildIndex = 2 * ChildIndex + 1;
}
}
}
static void heapSort(int Array[], int ArraySize) {
// 数组初始化:构建大顶堆
for (int i = ArraySize / 2 - 1; i >= 0; i--) {
heapSort_MaxTree(Array, i, ArraySize);// 从倒数一半的位置开始,后面的均为最底层树
}
// 依次排序并调整:从最后一个元素开始,不断缩小调整范围到第一个元素
for (int i = ArraySize - 1; i > 0; i--) {
// 交换Array[0]和Array[i],交换后Array[i]是Array[0到i]中最大的
swap(Array[0], Array[i]);
// 调整Array[0......i],使其仍为最大堆
heapSort_MaxTree(Array, 0, i);
}
}
8.桶排序
static int digitCount(long long Number) {
int Counter = 1;
while (Number /= 10)
Counter++;
return Counter;
}
static void bucketSort(int Array[], int ArraySize) {
// 获取最小值 最大值 确定桶的个数
int MinValue = Array[0], MaxValue = Array[0];
for (int i = 0; i < ArraySize; i++) {
if (MinValue > Array[i])
MinValue = Array[i];
if (MaxValue < Array[i])
MaxValue = Array[i];
}
// 根据位数来创建桶的个数
int BucketNum = digitCount(MaxValue);
double BucketRange = (double)(MaxValue - MinValue + 1) / BucketNum;
vector<vector<int>> Buckets(BucketNum);
// 初始化桶空间
for (int i = 0; i < BucketNum; i++) {
Buckets[i].reserve(ArraySize / BucketNum);
}
// 将元素放入对应的桶中
for (int i = 0; i < ArraySize; ++i) {
int BucketIndex = (int)((Array[i] - MinValue) / BucketRange);
Buckets[BucketIndex].push_back(Array[i]);
}
// 对桶内的元素进行排序
for (int i = 0; i < BucketNum; ++i)
sort(Buckets[i].begin(), Buckets[i].end());
// 将桶中的元素按顺序合并得到排序结果
int index = 0;
for (int i = 0; i < BucketNum; ++i) {
for (int j = 0; j < Buckets[i].size(); ++j)
Array[index++] = Buckets[i][j];
}
}
9.计数排序
void countSort(int Array[], int ArraySize) {
// 找出最大值与最小值
int Min = Array[0], Max = Array[0];
for (int i = 0; i < ArraySize; i++) {
if (Min > Array[i])
Min = Array[i];
if (Max < Array[i])
Max = Array[i];
}
// 根据最大值与最小值之间的元素个数开辟新数组
vector<int> Count(Max - Min + 1, 0);
for (int i = 0; i < ArraySize; i++) {
// 统计相同元素出现的次数
int OffSet = Array[i] - Min;
Count[OffSet]++;
}
for (int i = 0, Position = 0; i < Count.size(); i++) {
while ((Count[i]--) != 0) {
Array[Position] = i + Min;
Position++;
}
}
}
10.基数排序
int maxBit(int Array[], int ArraySize) {
int MaxValue = Array[0];
for (int i = 0; i < ArraySize; i++) {
if (MaxValue < Array[i])
MaxValue = Array[i];
}
int Counter = 1; // 最大位数
int Max = 10;
while (MaxValue >= Max) {
MaxValue /= 10;
Counter++;
}
return Counter;
}
void radixSort(int Array[], int ArraySize) {
// 十进制数,所以为10
int MaxCounter = maxBit(Array, ArraySize);
int *Temp = new int[ArraySize];
int *Count = new int[10]; // 计数器
int Radix = 1;
// MaxCounter次排序
for (int i = 1; i <= MaxCounter; i++) {
// 每次分配前清空计数器
for (int j = 0; j < 10; j++)
Count[j] = 0;
// 统计每个桶中的记录数
for (int j = 0; j < ArraySize; j++) {
int k = (Array[j] / Radix) % 10;
Count[k]++;
}
// 将Temp中的位置依次分配给每个桶
for (int j = 1; j < 10; j++)
Count[j] = Count[j - 1] + Count[j];
// 将所有桶中记录依次收集到tmp中
for (int j = ArraySize - 1; j >= 0; j--) {
int k = (Array[j] / Radix) % 10;
Temp[Count[k] - 1] = Array[j];
Count[k]--;
}
// 将临时数组Temp的内容复制到Array中
for (int j = 0; j < ArraySize; j++)
Array[j] = Temp[j];
Radix = Radix * 10;
}
}
AC代码:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
/* 1.冒泡排序(稳定):相邻元素相等时,它们并不会交换位置;时间复杂度O(n^2) */
void bubbleSort(int Array[], int ArraySize) {
for (int i = 0; i < ArraySize - 1; i++) {
for (int j = 0; j < ArraySize - 1 - i; j++) {
if (Array[j] > Array[j + 1]) {
int Temp = Array[j];
Array[j] = Array[j + 1];
Array[j + 1] = Temp;
}
}
}
}
/* 1.1.冒泡排序(优化):提升稳定性.有序时,时间复杂度为O(n) */
void bubbleSortAdvanced(int Array[], int ArraySize) {
bool SwapFlag = false;
for (int i = 0; i < ArraySize - 1; i++) {
SwapFlag = false;
for (int j = 0; j < ArraySize - 1 - i; j++) {
if (Array[j] > Array[j + 1]) {
swap(Array[j], Array[j + 1]);
SwapFlag = true;
}
}
if (SwapFlag == false)
break;
}
}
/* 2.选择排序(不稳定):记录最大元素及下标,遍历后调换元素位置.时间复杂度为O(n^2) */
void selectSort(int Array[], int ArraySize) {
for (int i = 0; i < ArraySize - 1; i++) {
int Index = i;
for (int j = i + 1; j < ArraySize; j++) {
if (Array[j] < Array[Index])
Index = j;
}
swap(Array[Index], Array[i]);
}
}
/* 3.插入排序:循环比较,每发现1个数,就开始调位.时间复杂度为O(n^2)*/
void insertSort(int Array[], int ArraySize) {
for (int i = 1; i < ArraySize; i++) {
for (int j = i; j > 0; j--) {
if (Array[j - 1] > Array[j])
swap(Array[j - 1], Array[j]);
else
break;
}
}
}
/* 4.快速排序:分为两半部分,进行递归.时间复杂度为O(nlogn) */
void quickSort(int Array[], int ArraySize, int Left, int Right) {
if (Left >= Right) return;
int i = Left, j = Right, Base = Array[Left];
while (i < j) {
while (Array[j] >= Base && i < j)
j--;
while (Array[i] <= Base && i < j)
i++;
if (i < j)
swap(Array[i], Array[j]);
}
Array[Left] = Array[i];
Array[i] = Base;
quickSort(Array, ArraySize, Left, i - 1);
quickSort(Array, ArraySize, i + 1, Right);
}
/* 5.希尔排序(非稳定):插入排序的改进,循环比较,每发现一个数,就开始调位.时间复杂度为O(n^2) */
void shellSort(int Array[], int ArraySize) {
for (int i = 0; i < ArraySize; i++) {
for (int j = i - 1; j >= 0 && Array[j + 1] < Array[j]; j--) {
swap(Array[j], Array[j + 1]);
}
}
}
/* 6.归并排序(稳定):递归将1个数组分成2部分分别排序.时间复杂度O(nlogn) */
void mergeArray(int Array[], int ArraySize, int Left, int Middle, int Right) {
int LeftSize = Middle - Left + 1, RightSize = Right - Middle;
// 创建临时数组来保存左右两部分的数据
vector<int> LeftTempArray(LeftSize), RightTempArray(RightSize);
// 将数据复制到临时数组中
for (int i = 0; i < LeftSize; ++i)
LeftTempArray[i] = Array[Left + i];
for (int j = 0; j < RightSize; ++j)
RightTempArray[j] = Array[Middle + 1 + j];
// 将临时数组中的数据按顺序合并到原始数组中
int i = 0, j = 0, k = Left;
while (i < LeftSize && j < RightSize) {
if (LeftTempArray[i] <= RightTempArray[j]) {
Array[k] = LeftTempArray[i];
i++;
}
else {
Array[k] = RightTempArray[j];
j++;
}
k++;
}
// 将剩余的元素复制到原始数组中
while (i < LeftSize) {
Array[k] = LeftTempArray[i];
i++;
k++;
}
while (j < RightSize) {
Array[k] = RightTempArray[j];
j++;
k++;
}
}
void mergeSort(int Array[], int ArraySize, int Left, int Right) {
if (Left >= Right)
return;
int Middle = Left + ((Right - Left) / 2);
mergeSort(Array, ArraySize, Left, Middle);
mergeSort(Array, ArraySize, Middle + 1, Right);
mergeArray(Array, ArraySize, Left, Middle, Right);
}
/* 7.堆排序(不稳定):近似完全二叉树,子节点的键值或索引总<(>)其父节点 */
void heapSort_MaxTree(int Array[], int StartIndex, int EndIndex) {
int ParentIndex = StartIndex; /* 父节点 */
int ChildIndex = 2 * StartIndex + 1; /* 子节点 */
while (ChildIndex < EndIndex) {
// 判断挑出 大的子节点 与 父节点 比较
if (ChildIndex + 1 < EndIndex && Array[ChildIndex] < Array[ChildIndex + 1])
ChildIndex++;
// 若父节点>子节点,则调整完毕.否则继续调整
if (Array[ParentIndex] > Array[ChildIndex])
return;
else {
// 交换父 子节点
swap(Array[ParentIndex], Array[ChildIndex]);
ParentIndex = ChildIndex;
ChildIndex = 2 * ChildIndex + 1;
}
}
}
void heapSort(int Array[], int ArraySize) {
// 数组初始化:构建大顶堆
for (int i = ArraySize / 2 - 1; i >= 0; i--) {
heapSort_MaxTree(Array, i, ArraySize);// 从倒数一半的位置开始,后面的均为最底层树
}
// 依次排序并调整:从最后一个元素开始,不断缩小调整范围到第一个元素
for (int i = ArraySize - 1; i > 0; i--) {
// 交换Array[0]和Array[i],交换后Array[i]是Array[0到i]中最大的
swap(Array[0], Array[i]);
// 调整Array[0......i],使其仍为最大堆
heapSort_MaxTree(Array, 0, i);
}
}
/* 8.桶排序:将待排序数组映射到不同的桶内,保证桶内有序,再反向输出 */
int digitCount(long long Number) {
int Counter = 1;
while (Number /= 10) Counter++;
return Counter;
}
void bucketSort(int Array[], int ArraySize) {
// 获取最小值 最大值 确定桶的个数
int MinValue = Array[0], MaxValue = Array[0];
for (int i = 0; i < ArraySize; i++) {
if (MinValue > Array[i])
MinValue = Array[i];
if (MaxValue < Array[i])
MaxValue = Array[i];
}
// 根据位数来创建桶的个数
int BucketNum = digitCount(MaxValue);
double BucketRange = (double)(MaxValue - MinValue + 1) / BucketNum;
vector<vector<int>> Buckets(BucketNum);
// 初始化桶空间
for (int i = 0; i < BucketNum; i++) {
Buckets[i].reserve(ArraySize / BucketNum);
}
// 将元素放入对应的桶中
for (int i = 0; i < ArraySize; ++i) {
int BucketIndex = (int)((Array[i] - MinValue) / BucketRange);
Buckets[BucketIndex].push_back(Array[i]);
}
// 对桶内的元素进行排序
for (int i = 0; i < BucketNum; ++i)
sort(Buckets[i].begin(), Buckets[i].end());
// 将桶中的元素按顺序合并得到排序结果
int index = 0;
for (int i = 0; i < BucketNum; ++i) {
for (int j = 0; j < Buckets[i].size(); ++j)
Array[index++] = Buckets[i][j];
}
}
/* 9.计数排序:开辟新的数组;原数组值映射为新数组的键值,原数组值的个数为新数组的数值 */
void countSort(int Array[], int ArraySize) {
// 找出最大值与最小值
int Min = Array[0], Max = Array[0];
for (int i = 0; i < ArraySize; i++) {
if (Min > Array[i])
Min = Array[i];
if (Max < Array[i])
Max = Array[i];
}
// 根据最大值与最小值之间的元素个数开辟新数组
vector<int> Count(Max - Min + 1, 0);
for (int i = 0; i < ArraySize; i++) {
// 统计相同元素出现的次数
int OffSet = Array[i] - Min;
Count[OffSet]++;
}
for (int i = 0, Position = 0; i < Count.size(); i++) {
while ((Count[i]--) != 0) {
Array[Position] = i + Min;
Position++;
}
}
}
/* 10.基数排序(稳定):将数字按个十百分开,每位进行比较 */
int maxBit(int Array[], int ArraySize) {
int MaxValue = Array[0];
for (int i = 0; i < ArraySize; i++) {
if (MaxValue < Array[i])
MaxValue = Array[i];
}
int Counter = 1; // 最大位数
int Max = 10;
while (MaxValue >= Max) {
MaxValue /= 10;
Counter++;
}
return Counter;
}
void radixSort(int Array[], int ArraySize) {
// 十进制数,所以为10
int MaxCounter = maxBit(Array, ArraySize);
int *Temp = new int[ArraySize];
int *Count = new int[10]; // 计数器
int Radix = 1;
// MaxCounter次排序
for (int i = 1; i <= MaxCounter; i++) {
// 每次分配前清空计数器
for (int j = 0; j < 10; j++)
Count[j] = 0;
// 统计每个桶中的记录数
for (int j = 0; j < ArraySize; j++) {
int k = (Array[j] / Radix) % 10;
Count[k]++;
}
// 将Temp中的位置依次分配给每个桶
for (int j = 1; j < 10; j++)
Count[j] = Count[j - 1] + Count[j];
// 将所有桶中记录依次收集到tmp中
for (int j = ArraySize - 1; j >= 0; j--) {
int k = (Array[j] / Radix) % 10;
Temp[Count[k] - 1] = Array[j];
Count[k]--;
}
// 将临时数组Temp的内容复制到Array中
for (int j = 0; j < ArraySize; j++)
Array[j] = Temp[j];
Radix = Radix * 10;
}
}
template<typename T_Whz>
void myPrintf(T_Whz Array[], T_Whz ArraySize) {
for (int i = 0; i < ArraySize; i++) {
cout << Array[i] << ' ';
}
cout << endl;
}
int main() {
int Array[] = { 9,1,5,8,3,7,4,6,2 };
int ArraySize = sizeof(Array) / sizeof(Array[0]);
cout << "Before Sort:" << endl;
myPrintf(Array, ArraySize);
radixSort(Array, ArraySize);
cout << "After Sort:" << endl;
myPrintf(Array, ArraySize);
mergeSort(Array, ArraySize, 0, ArraySize - 1);
cout << "After quickSort:" << endl;
myPrintf(Array, ArraySize);
system("pause");
return 0;
}