参考博文:各种排序-从这篇文章中记录了学习笔记(搬运过来),掌握了原理,代码一定要结合图解手撸一遍。
1、冒泡排序
。。。待写
2、选择排序
2.1 算法思想
- 在未排序的序列中找到
最小(大)元素 ,存放到排序序列的起始位置 。 - 从剩下
未排序 元素中继续寻找最小(大)元素 ,然后放到自己已排序 的序列的末尾。 - 以此类推,直到所有元素排序完毕。
时间复杂度O(n^2)
2.2 图解 2.3 代码
void selectionSort(int* arr,int len)
{
for (int i = 0; i < len - 1; i++)
{
int min = i;
for (int j = i + 1; j < len; j++)
{
if (arr[j] < arr[min])
min = j;
}
swap(arr[i], arr[min]);
}
}
3、插入排序
3.1 算法思想 将无序元素 插到有序元素 中去
- 步骤1: 从第一个元素开始,该元素可以认为已经被排序;
- 步骤2: 取出下一个元素,在已经排序的元素序列中从后向前扫描;
- 步骤3: 如果该元素(已排序)大于新元素,将该元素移到下一位置(腾位置);
- 步骤4: 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;
- 步骤5: 将新元素插入到该位置后;
- 步骤6: 重复步骤2~5。
时间复杂度O(n^2),不稳定,
3.2 图解
3.3 代码
void insertSort(int* arr,int len)
{
for (int i = 1; i < len; i++)
{
int temp = arr[i];
int j = i - 1;
while (j >= 0 && temp < arr[j])
{
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = temp;
}
}
4、快速排序
4.1 算法思想
- 选第一个数为标准。
- 将比基准小的数据交换到前面,比基准大的交换到后面
- 对左边的空间和右边的空间重复,直到各区间只有一个数字
4.2 图解
4.3 代码
void quickSort(int* arr,int left,int right)
{
if (left >= right) return;
int begin = left;
int end = right;
int key = arr[end];
while (begin < end)
{
while (begin < end && arr[begin] <= key) begin++;
arr[end] = arr[begin];
while (begin < end && arr[end] >= key) end--;
arr[begin] = arr[end];
}
arr[end] = key;
quickSort(arr, left, end - 1);
quickSort(arr, end + 1, right);
}
5、堆排序
5.1 算法思想
- 如果要从小到大排序,建立大堆,根节点大于左右子树。
- 将根结和最后一个元素交换,并且树的元素个数减1。
- 重复1~2,直到只剩一个元素。
参考博文:堆排序(C语言)
定义了以下几种操作: (1)最大堆调整(Heapify):将堆的末端子节点作调整,使得子节点永远小于父节点 (2)创建最大堆(CreateHeap):将堆中的所有数据重新排序 (3)堆排序(HeapSort):移除位在第一个数据的根节点,并做最大堆调整的递归运算
堆 是一个近似完全二叉树的结构 数组a[k]与二叉树的性质: 父节点:(k-1)/2 左子节点:2k+1 右子节点:2k+2
5.2 图解
5.3 代码
void heapify(int* arr,int len,int k)
{
if (k < len)
{
int max = k;
int s1 = 2 * k + 1;
int s2 = 2 * k + 2;
if (s1<len && arr[s1]>arr[max]) max = s1;
if (s2<len && arr[s2]>arr[max]) max = s2;
if (max != k)
{
swap(arr[max], arr[k]);
heapify(arr, len, max);
}
}
}
void heapSort(int* arr, int len)
{
int last_node = len - 1;
int last_parent = (last_node - 1) / 2;
for (int i = last_parent; i >= 0; i--)
heapify(arr, len, i);
for (int i = len - 1; i >= 0; i--)
{
swap(arr[0], arr[i]);
heapify(arr, i, 0);
}
}
6、希尔排序
6.1 算法思想 将数组元素分成若干组,每组分别进行插入排序 ,使整个数组逐渐变成部分有序数组,再慢慢减少所分的组数,最终合并成一个组 。
将数组多次分组,分别进行插入排序—改进的插入排序。
参考博文:排序算法之希尔排序、希尔排序C++实现
6.2 图解
6.3 代码
void shellSort(int* arr,int len)
{
int group = len / 2;
while (group >= 1)
{
for (int i = group; i < len; i++)
{
int temp = arr[i];
int j = i - group;
while (j>=0&&temp<=arr[j])
{
arr[j + group] = arr[j];
j = j - group;
}
arr[j + group] = temp;
}
group /= 2;
}
}
7、计数排序
7.1 算法思想
- 1、找出待排序的数组
最大 和最小 的元素 - 2、统计数组中每个值为
i∈[min:1:max] 的元素出现的个数,存入数组c的第i-min项 - 将下标+min的值根据在数组c中的个数存到
原数组 中。
本算法图解更容易理解
7.2 图解
7.3 代码 时间复杂度:O(n+k),n容量的原数组,k容量的计数数组,实际分别遍历了两个数组,所有好坏情况都是O(n+k)。 空间复杂度:O(k),新建了k容量的计数数组。
void countSort(int* arr, int len)
{
int min = arr[0];
int max = arr[0];
for (int i = 0; i < len; i++)
{
if (arr[i] < min) min = arr[i];
if (arr[i] > max) max = arr[i];
}
int len_count = max - min + 1;
int* arr_count = new int[len_count];
for (int i_count = 0; i_count < len_count; i_count++)
arr_count[i_count] = 0;
for (int i = 0; i < len; i++)
{
arr_count[arr[i] - min] += 1;
}
int i_total = 0;
for (int i_count = 0; i_count < len_count; i_count++)
{
for (int i_temp = 0; i_temp < arr_count[i_count]; i_temp++)
{
arr[i_total++] = min + i_count;
}
}
}
8、基数排序
8.1 算法思想
- 取得数组中的最大数,并取得
位数 。 - 根据个位数值大小,对数组进行排序(实际放
0~9的桶 里进行计数排序); - 重复上一步骤,依次根据更高位数值进行排序,直至到达最高位;
参考博文:C++排序算法之基数排序
8.2 图解
8.3 代码
int maxBit(int* arr, int len)
{
int bit_num = 0;
for (int i = 0; i < arr[i]; i++)
{
int temp = arr[i];
int bit_temp = 0;
while (temp > 0)
{
temp /= 10;
bit_temp++;
}
if (bit_temp > bit_num)
bit_num = bit_temp;
}
return bit_num;
}
void radixSort(int* arr, int len)
{
int bit_max = maxBit(arr, len);
vector<vector<int>> buckets(10);
int r = 1;
for (int i_bit = 0; i_bit < bit_max; i_bit++)
{
for (int i = 0; i < len; i++)
{
int num_temp = (arr[i] / r) % 10;
buckets[num_temp].push_back(arr[i]);
}
int i_origin = 0;
for (int i_bucket = 0; i_bucket < 10; i_bucket++)
{
if (!buckets[i_bucket].size()) continue;
for (vector<int>::iterator itr_num = buckets[i_bucket].begin(); itr_num != buckets[i_bucket].end(); itr_num++)
{
arr[i_origin++] = *itr_num;
}
buckets[i_bucket].clear();
}
r *= 10;
}
}
9、桶排序
9.1 算法思想
是计数排序的进化版
- 设置一个定量的数组当作
空桶子 。 - 寻访序列,并且把项目一个一个
放到对应的桶子 去(将数组分段划分、按位数划分等)。 - 对每个非空的桶子进行
排序 (其他适合小范围的排序,如插入排序)。 - 从不是空的桶子里把项目再放回原来的序列中。
参考博文:C/C++桶排序
9.2 图解
9.3 代码
void bucketSort(int* arr, int len)
{
int min_value = arr[0];
int max_value = arr[0];
for (int i = 1; i < len; i++)
{
if (arr[i] < min_value) min_value = arr[i];
if (arr[i] > max_value) max_value = arr[i];
}
int bucketsize = 5;
int buckets_num = (max_value - min_value) / bucketsize + 1;
vector<vector<int>> buckets(buckets_num);
for (int i = 0; i < len; i++)
{
int index = (arr[i] - min_value) / bucketsize;
buckets[index].push_back(arr[i]);
}
int i_origin = 0;
for (int i_bucket = 0; i_bucket < buckets_num; i_bucket++)
{
if (!buckets[i_bucket].size()) continue;
for (int i_sort = 1; i_sort < buckets[i_bucket].size(); i_sort++)
{
int temp_sort = buckets[i_bucket][i_sort];
int j_sort = i_sort - 1;
while (j_sort >= 0 && temp_sort < buckets[i_bucket][j_sort])
{
buckets[i_bucket][j_sort + 1] = buckets[i_bucket][j_sort];
j_sort--;
}
buckets[i_bucket][j_sort + 1] = temp_sort;
}
for (int i_sort = 0; i_sort < buckets[i_bucket].size(); i_sort++)
{
arr[i_origin++] = buckets[i_bucket][i_sort];
}
}
}
/--------------------------------------------------------------------------------------------------------------------------------/
x、排序
x.1 算法思想
x.2 图解
x.3 代码
|