算法设计与分析
这门课程里会用到好多以前学到的算法!可是都被我遗忘了...
所以我来浅浅记录一下,那些曾经在我脑子里住过一段时间的代码们!
目录
堆排序
堆是一种经过排序的完全二叉树
基本思想:
- 需要调整堆、堆排序(调用调整堆函数)两个函数
- 考虑原数组下标,最小下标为0或1的两种情况会导致结点和左孩子的下标关系不同(下方有举例),!一定要明确这个点,在主函数中如for循环的取值会有不同
- 将数组转换为完全二叉树后,需要调整堆使其变为大根堆或小根堆
- 排序时是将根结点的数(即数组中第一个数,假设为num【0】)与堆(数组)中未确定位置的最后一个数(假设为num【i】)进行交换
- 这时,就确定了被换到最后一位的数(根据大根堆和小根堆的概念,这个数一定是最大或最小的数)的位置(下标,i),再对num【i】之前的结点进行调整
- 若要得到升序数组,则开始要构建大根堆;若要得到降序数组,则开始要构建小根堆
最小下标为0
void heapadjust(int* num, int len, int i) {
/*
num是数组
len是数组大小(下同)
i是将要调整的结点(数组下标)
*/
int key = num[i];
for (int j = i * 2 + 1; j < len; j = j * 2 + 1) { //最小下标为0和1的第一个区别点
if (j<len - 1 && num[j] > num[j + 1])
j++;
if (num[j] < key) {
num[i] = num[j];
i = j;
}
}
num[i] = key;
}
void heapsort(int* num, int len) {
for (int j = len / 2 - 1; j >= 0; j--) { //最小下标为0和1的第二个区别点
heapadjust(num, len, j);
}
for (int i = len - 1; i > 0; i--) { //最小下标为0和1的第三个区别点
int temp = num[i];
num[i] = num[0];
num[0] = temp;
heapadjust(num, i, 0);
}
}
最小下标为1
void heapadjust(int* num, int len, int i) {
int j;
int tmp = num[i];
for (j = 2 * i; j <= len; j *= 2) {
if (j < len&& num[j] < num[j + 1]) {
j++;
}
if (num[j] > tmp) {
num[i] = num[j];
i = j;
}
}
num[i] = tmp;
}
void heapsort(int* num, int len) {
for (int i = len / 2; i > 0; i--) {
heapadjust(num, len, i);
}
for (int i = len; i > 0; i--) {
int tmp = num[i];
num[i] = num[1];
num[1] = tmp;
heapadjust(num, i - 1, 1);
}
}
主函数中,再根据要求调用heapsort函数即可完成堆排序。
堆排序的基本思路:❗堆排序❗基本思路 学习记录 防止遗忘 浅浅记录一下~_哔哩哔哩_bilibili-https://b23.tv/KwsQ18W
快速排序
相较于堆排序,快速排序的算法思路简单一些:
- 随机取数组中的一个数(默认选择第一个数),将它作为key
- 取两个标记位i和j,分别从key后面一个数、最后一个数开始遍历
- 先取j从最后一个数开始遍历,若num【j】>=key,则j--;若num【j】<key,则将num【j】放入原先key的位置,此时,num【j】处的位置空出来了,结束循环
- 再取i从原先key位置的后一个位置开始遍历,若num【i】<=key,则i++;若num【i】>key,则将num【i】放入上述空位置中,结束循环
- 重复i和j的遍历直到i=j,将key放入最后一个空位置中
- 一次遍历之后得到数组,可以发现key左边都是小于key的数,key右边都是大于key的数
- 对key左右两边(还未有序)再次调用本函数,直到全部排序完毕
void sort(int* num, int low, int high) {
if (low > high) return;
int i = low;
int j = high;
int key = num[low];
while (i < j) {
while (i<j && num[j]>=key) {
j--;
}
num[i] = num[j];
while (i < j && num[i] <= key) {
i++;
}
num[j] = num[i];
}
num[i] = key;
sort(num, low, i - 1); //快排key左边的数
sort(num, i + 1, high); //快排key右边的数
}
主函数中,再根据要求调用sort函数即可完成快速排序。
快速排序还有很多衍生的相似算法,如解决将所有奇数排到偶数左边的问题时,可借鉴快速排序算法;如解决寻找数组中最小k的数的问题,可采用线性选择算法,是快速排序的一种优化。