记录并分享一下学习经验٩(^ᴗ^)۶
1.算法复杂度比较
2.算法实现
以下实现排序均为由小到大,且传入均为vector<int>类型。
class Sort {
public:
/* 插入排序
* 遍历 并维护一个有序序列
* 遍历到一个数据时进行与维护的有序序列比较
* 大于 维护的有序序列的尾部(最大值)则不处理
* 小于 维护的有序序列的尾部(最大值)则找到正确的位置插入
*/
void insertion_sort(vector<int>& arr){
int n = arr.size();
for (int i = 1; i < n; i++){
int j = i;
int temp = arr[i];
while (j > 0 && temp < arr[j - 1]){
arr[j] = arr[j - 1];
j--;
}
arr[j] = temp;
}
}
/* 希尔排序
* 先分组 再插入排序 将数组变为“基本有序”的状态
* 插入排序 plus版 插入排序在处理“基本有序”的数组时效率很高
*/
void shell_sort(vector<int>& arr){
int n = arr.size();
int h = 1;
while (h < n / 3) {
h = 3 * h + 1;
}
while (h >= 1) {
for (int i = h; i < n; i++) {
for (int j = i; j >= h && arr[j] < arr[j - h]; j -= h) {
swap(arr[j], arr[j - h]);
}
}
h = h / 3;
}
}
/* 选择排序
* 遍历 找到最大元素 放到尾部
*/
void selection_sort(vector<int>& arr){
int n = arr.size();
for (int i = 0; i < n; i++){
int minIndex = i;
for (int j = i + 1; j < n; j++){
if (arr[j] < arr[minIndex]){
minIndex = j;
}
}
swap(arr[i], arr[minIndex]);
}
}
/* 堆排序
* 类似完全二叉树的结构
* 每次找到最大值 并且维持树的结构 最后将最大值放到队尾
*/
void heap_sort(vector<int>& arr){
int n = arr.size();
//初始化顶堆
for (int i = n / 2 - 1; i >= 0; i--){
Heap_helper(arr, i, n - 1);
}
//最顶上的一定为最大
for (int i = n - 1; i > 0; i--) {
//将最大的元素放到未排序序列的尾部
swap(arr[0], arr[i]);
//维护顶堆结构
Heap_helper(arr, 0, i - 1);
}
}
void Heap_helper(vector<int>& arr, int l, int r){
//父节点与子节点在数组中的位置
int dad = l;
int son = dad * 2 + 1;
while (son <= r) {
//选择较大的子节点
if (son + 1 <= r && arr[son] < arr[son + 1])
son++;
//父节点最大则返回
if (arr[dad] > arr[son])
return;
else { //子节点大 则交换节点 继续往下
swap(arr[dad], arr[son]);
dad = son;
son = dad * 2 + 1;
}
}
}
/* 冒泡排序
* 比较相邻元素,不是预期大小则交换
*/
void bubble_sort(vector<int>& arr){
int n = arr.size();
int sign;
for (int i = 0; i < n; i++){
sign = 1;
for (int j = 1; j < n - i; j++){
if (arr[j] < arr[j - 1]){
swap(arr[j], arr[j - 1]);
sign = 0;
}
}
if (sign)break;
}
}
/* 快速排序
* 在数组找一个“基准”比它大的放在它前面 比它小的放在它后面
*/
void quick_sort(vector<int>& arr){
int n = arr.size();
Quick_helper(arr, 0, n - 1);
}
void Quick_helper(vector<int>& arr, int l, int r){
if (l >= r)
return;
int mid = arr[r];
int left = l, right = r - 1;
while (left < right) {
while (arr[left] < mid && left < right)
left++;
while (arr[right] >= mid && left < right)
right--;
swap(arr[left], arr[right]);
}
//判断中间的属于那一边
if (arr[left] >= arr[r])
swap(arr[left], arr[r]);
else
left++;
Quick_helper(arr, l, left - 1);
Quick_helper(arr, left + 1, r);
}
/* 归并排序
* 分治法 先分成小组 保证小组内有序 再将小组与小组合并
*/
void merge_sort(vector<int>& arr){
int n = arr.size();
Merge_Sort(arr, 0, n - 1);
}
void Merge_Sort(vector<int>& arr, int l, int r){
if (l == r){
return;
}
else {
int m = (l + r) / 2;
Merge_Sort(arr, l, m);
Merge_Sort(arr, m + 1, r);
Merge_helper(arr, l, m, r);
}
}
void Merge_helper(vector<int>& arr, int l, int m, int r){
vector<int> temp = vector<int>(r - l + 1);
//l-m是前一半 m-r是后一半 两半均为有序 以下实现合并两个有序数组
int k = l, i = l, j = m + 1;
while (i <= m && j <= r){
if (arr[i] <= arr[j]){
temp[k++] = arr[i++];
}
else{
temp[k++] = arr[j++];
}
}
//有一半已经排序完 将另一半剩下的补上
while (i <= m) temp[k++] = arr[i++];
while (j <= r) temp[k++] = arr[j++];
for (int i = l; i<k; i++){
arr[i] = temp[i];
}
}
/* 基数排序
* 按数位排序
*/
void radix_sort(vector<int>& arr){
int n = arr.size();
//求出最高位
int d = Radix_helper(arr);
vector<int> temp(n);
//count用来记录数组在某位上0~9分别的数量
vector<int> count(10, 0);
int i, j, k;
int radix = 1;
//按位排序
for (i = 1; i <= d; i++){
//计数器清零
count = vector<int>(10, 0);
for (j = 0; j < n; j++){
k = (arr[j] / radix) % 10;
count[k]++;
}
for (j = 1; j < 10; j++){
//累加 方便在对应的位置存放数据
count[j] = count[j - 1] + count[j];
}
for (j = n - 1; j >= 0; j--){
//把数组按照 当前位 的大小排序
k = (arr[j] / radix) % 10;
temp[count[k] - 1] = arr[j];
count[k]--;
}
arr = temp;
//下一位
radix = radix * 10;
}
}
int Radix_helper(vector<int>& arr){
int n = arr.size();
//先找到最大值 再求最大位数
int maxData = arr[0];
for (int i = 1; i < n; ++i)
{
if (maxData < arr[i])
maxData = arr[i];
}
int d = 1;
int p = 10;
while (maxData >= p)
{
maxData /= 10;
++d;
}
return d;
}
};
1.0 十大经典排序算法 | 菜鸟教程 (runoob.com)https://www.runoob.com/w3cnote/ten-sorting-algorithm.html这里面有每个排序的动画,可以参考一下