导言:此文章主要用于简要复习常出现于高校算法课上的经典算法,如要详细学习还请查看其它教学
1. 排序
1.1 归并排序
a.算法思想
通过分治来排序
1.将所有元素划分成两组,而后分别递归完成较小问题的排序
2.对这两个序列表进行某种形式交错 而 合并成一个有序的序列表
b. 简单图示
1 2 3 4 5 6 7 8 9 → [1 2 3 4 5] + [6 7 8 9]
暂时只演示右侧的 [6 7 8 9] → [6 7] + [8 9]
[8 9] → [8] + [9] →合并 sort() → [8] < [9] ? [8 9] : [9 8]; 接着递归
c. 时间复杂度: O(n log n)
d.代码示例
注:这里所有的算法的代码实现都不唯一,主要是算法思想
void mergesort(item_type s[], int low, int high)
{
int middle; //中间元素下标
if (low < high) {
middle = (high - low) / 2 + low; //防止值溢出
mergesort(s, low, middle);
mergesort(s, middle+1, high);
merge(s, low, middle, high);
}
}
void merge(itme_type s[], int low, int middle, int high)
{
int i; // 计数器
item_type l[middle-low+1], r[high-middle];//用于暂时存放待归并元素
item_type *lb=l, *le=l, *rb=r, *re=r;
for(i = low; i <= middle; ++i,++le)
*le = s[i];
for(; i <= high; ++i,++re)
*re = s[i];
// 归并
i = low;
while((lb != le) && (rb != re)){
if(*lb <= *rb)
s[i++] = *lb++;
else
s[i++] = *rb++;
}
// 归并剩余序列
while(lb != le)
s[i++] = *lb++;
while(rb != re)
s[i++] = *rb++;
}
1.2 快速排序
a.算法思想
通过随机化来排序
1.从序列中随机选择一项 记为p (枢纽元)
2.通过 p 将序列分成两队 一对为在序关系下所有排在 p 之前的项;另一对为在序关系下所有排在 p 之后的项
3.在两队序列中重复 1 和 2 的步骤, 直至序列完全有序
b.简单图示
黄色背景为 标记p(枢纽元) 蓝色则为有序
21 3 46 16 31 24 8
3 8 46 16 31 24 21
3 8 16 21 46 31 24
3 8 16 21 24 31 46
3 8 16 21 24 31 46
c.时间复杂度: O(n log n)
c.代码示例
PS: 如果代码里的注释或图示 难以理解,可直接拿图示的序列手动演示代码的运行过程
void quicksort(item_type s[], int l, int h)
{
int p; // 划分点下标 即枢纽元 p
if ((h - l) > 0){
p = partition(s, l, h);
quicksort(s, l, p-1);
quicksort(s, p+1, h);
}
}
int partition(item_type s[], int l, int h)
{
int i; // 计数器
int p; // 枢纽元(本程序选择 h 位置为枢纽元)
int firsthigh; // 表示枢纽元排序后的位置 可暂时表示枢纽元目前该在的位置
p = h;
firsthigh = l;
for (i = 1; i < h; ++i)
if (s[i] < s[p]){// 满足条件时 表明s[i] 应该排在枢纽元之前的序列队
swap(&s[i], &s[firsthigh]);// 将s[i] 放至枢纽元之前的队伍
++firsthigh;// 枢纽元位置之前的队伍新增一项 枢纽元位置向后移一位
}
swap(&s[p], &s[firsthigh]);
return firsthigh;
}
1.3 冒泡排序
a. 算法思想
每次比较 i 与 i+1 的元素,如何 i 比 i+1 的元素大或小 就把 i 与 i+1 的元素交换,此为冒泡
b.时间复杂度 : O(n log n)
c.代码示例
void bubbleSort(int arr[], int n) {
for (int i = 0; i < n-1; i++) {
for (int j = 0; j < n-i-1; j++) {
if (arr[j] > arr[j+1]) {
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
1.4 选择排序
a.算法思想
遍历 n 次无序序列, 每次遍历无序序列找到 最小/最大 的值, 然后将这个 最值 与无序序列的第一个元素交换 (有序序列的后面),与前面的有序序列组成有序序列
b.时间复杂度 : O(n ^ 2)
c.代码示例
void selectionSort(int arr[], int n) {
for (int i = 0; i < n-1; i++) {
int minIndex = i;
for (int j = i+1; j < n; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
int temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
1.5 插入排序
a. 算法思想
将无序序列的第一个元素插入到有序序列中合适的位置
b.时间复杂度: O(n ^ 2)
c.代码示例
void insertionSort(int arr[], int n) {
for (int i = 1; i < n; i++) {
int key = arr[i];
int j = i - 1;
while (j >= 0 && arr[j] > key) {
arr[j+1] = arr[j];
j--;
}
arr[j+1] = key;
}
}