1、直接插入(对于基本有序的数组时,最优选👍)
1)默认第一个数据已完成排序
2)依次取下一个元素向前依次比较
若小于前一元素,则交换位置,大于则位置不变
void insert() {
for (int i = 0; i < max - 1; i++) {
int end = i;
int tem = a[end + 1];
while (end >= 0) {
if (tem < a[end]) {
//将大值后移
a[end + 1] = a[end--];//注意是end--
} else
break;
}
//end+1:因为前面if执行后end减一,固end+1,放tem
a[end + 1] = tem;
}
}
2、希尔排序
1) 选增量gap(gap=n/2,即将其分为2组)
2)分别对每组进行插入排序
3)重分gap(gap/=2,直至gap=1)
void xier() {
int n = max;
while (n > 1) {
n = n / 2;
for (int i = 0; i < max - n; i++) {
//直接插入排序
int end = i;
int tem = a[end + n];
while (end >= 0) {
if (tem < a[end]) {
a[end + n] = a[end];
end -= n;
} else
break;
}
a[end + n] = tem;
}
}
}
3、选择排序
1)找出数据中的最小值,将其与第一个值交换位置
2)继续找待排数据中的最小值,将其与第二个值交换位置
3)重复上述步骤,直至最后一个值
void swap(int *a, int *b) {
int tem = *a;
*a = *b;
*b = tem;
}
void xuanze(int *arr) {
int begin = 0, end = max - 1;
while (begin < end) {
int Min = begin, Max = begin;
//找最大、最小值的下标
for (int i = begin; i <= end; i++) {
//找最小值下标
if (arr[i] < arr[Min])
Min = i;
//找最大值下标
if (arr[i] > arr[Max])
Max = i;
}
//放最小值到前面
swap(&arr[Min], &arr[begin]);
//防止最大值在begin处被换走(巨关键@_@)
if (begin == Max)
Max = Min;
//放最大值到后面
swap(&arr[Max], &arr[end]);
begin++;
end--;
}
}
4、冒泡排序
1)从前到后依次,两两比较
若前>后,交换两者位置
若前<后,用后继续向后比较
void maopao() {
int n = max;
while (n--) {
int flag = 0;
for (int i = 1; i < max; i++) {
if (a[i - 1] > a[i]) {
swap(&a[i-1],&a[i]);
flag = 1;
}
if (flag = 0)
break;
}
}
}
5、快速排序(左右指针法)
(指针分别指向最左和最右)
1)选其中之一为分界值:key
2)左指针向右走,右指针向左走,并与key比较
若 右<key,则右指针将值赋给左指针,且左指针右移
若 右>key,则右指针左移
若 左<key,则左指针右移
若 左>key,则左指针将值赋给右指针,且右指针左移
(将小于key的放数组左边,大于的放右边)
3)当左右指针相遇时,让其等于key
4)左侧可再找一个key,继续重复上述步骤。右侧同理(递归)
void quick(int low, int high) {
int i = low, j = high;
if (i >= j)
return;
int tem = a[low];
while (i != j) {
while (a[j] >= tem && i < j)
j--;
while (a[i] <= tem && i < j)
i++;
if (i < j) {
int x = a[i];
a[i] = a[j];
a[j] = x;
}
}
int x = a[low];
a[low] = a[i];
a[i] = x;
quick(low, i - 1);
quick(i + 1, high);
}
6、堆排序
1)构建堆(类似于二叉排序树)(升序用大根堆,降序用小根堆)
大根堆:每个节点的值都大于等于左右孩子节点
小根堆:每个节点的值都小于等于左右孩子节点
- 从叶子节点开始向上比较
若 大于根节点,则交换位置(反之则不变)
2)将堆顶与最后一个元素交换位置
- 换后末尾元素不变,其他元素继续向上重构堆
//建立堆
//二叉树规律:找最后一节点的父节点:father=(len-1-1)/2
//固可得其左右子树(排最后的)L=father*2+1,R=father*2+1+1=len
void build(int *arr, int start, int end) {
int temp = arr[start];
for (int i = 2 * start + 1; i <= end; i = i * 2 + 1) {
if (i < end && arr[i] < arr[i + 1])
i++;
if (arr[i] > temp) {
arr[start] = arr[i];
start = i;
} else
break;
}
arr[start] = temp;
}
//堆排序
void duipai(int *arr) {
int len = max;
for (int i = (len - 1 - 1) / 2; i >= 0; i--)
//i:最后一个父节点
build(arr, i, len - 1);
int temp;
//将栈顶放置末尾,即将最大值放置最后
for (int i = 0; i < len - 1; i++) {
swap(&arr[0],&arr[len-1-i]);
//重构堆顶
build(arr, 0, len - 1 - i - 1);
}
}