声明: 以下是我们学校在学习数据结构时进行的实训,如涉及侵权马上删除文章
声明:本文主要用作技术分享,所有内容仅供参考。任何使用或依赖于本文信息所造成的法律后果均与本人无关。请读者自行判断风险,并遵循相关法律法规。
实训八 排序算法实现(二)
一、实训类型
验证性实训
二、实训目的与任务
1. 掌握简单选择排序算法的基本思想;
2. 掌握简单选择排序算法的实现方法;
3. 验证简单选择排序算法的时间性能;
4. 掌握堆排序算法的基本思想;
5. 掌握堆排序算法的实现方法;
6. 验证堆排序算法的时间性能;
7. 掌握归并排序算法的基本思想;
2. 掌握归并排序算法的实现方法;
3. 验证归并排序算法的时间性能。
三、实训基本原理
1. 简单选择排序
简单选择排序(Simple Selection Sort)是选择排序中最简单的排序方法,其基本思想是:第i趟排序通过n-i次关键码的比较,在n-i+1(1≤i≤n-1)个记录中选取关键码最小的记录,并和第i个记录交换作为有序序列的第i个记录。
r1 ≤r2 … … ≤ri-1 ri ri+1 … rmin … rn 有序区 无序区 已经位于最终位置 rmin为无序区的最小记录 |
交换 |
2.堆排序
简单选择排序没有把每一趟的比较结果保留下来。在后一趟的比较中,有许多比较在前一趟已经做过了,但由于前一趟排序时未保留这些比较结果,所以,后一趟排序时又重复执行这些比较操作,因而记录的比较次数较多。
堆排序(Heap Sort)是简单选择排序的一种改进,改进的着眼点是:减少关键码的比较次数。堆排序利用每趟比较后的结果,也就是在找出关键码最小记录的同时,也找出关键码较小的记录,减少了在后面的选择中的比较次数,从而提高整个排序的效率。
堆排序是利用堆(假设利用大根堆)的特性进行排序的方法,其基本思想是:首先将待排序的记录序列构造成一个堆,此时,选出了堆中所有记录的最大者即堆顶记录,然后将它和堆中最后一个记录交换,并将剩余的记录再调整成堆,这样又找出了次大的记录,以此类推,直到堆中只有一个记录为止。
r1 r2 … … ri ri+1 ≤… … ≤rn-1 ≤rn 无序区 有序区 为一个堆 已经位于最终位置 |
堆顶和堆中最后一个记录交换 |
3.归并排序
归并排序是一种借助“归并”进行排序的方法。归并的含义是将两个或两个以上的有序序列归并成一个有序序列的过程。
归并排序的主要思想是:将若干有序序列逐步归并,最终归并为一个有序序列。
二路归并排序是归并排序中最简单的排序方法,其基本思想是:将若干个有序序列进行两两归并,直至所有待排序记录都在一个有序序列为止。
四、实训设备
1.计算机
五、实训内容
1. 对一组数据进行选择排序(按升序排列)。
2. 对一组数据进行堆排序(按升序排列)。
3. 对一组数据进行一趟二路归并排序(按升序排列)。
代码:
- 对一组数据进行选择排序(按升序排列)
#include <stdio.h>
// 选择排序函数(升序)
void SelectSort(int r[], int n) {
int i, j, k, temp;
for (i = 0; i < n - 1; i++) {
k = i;
for (j = i + 1; j < n; j++) {
if (r[j] < r[k])
k = j;
}
if (k!= i) {
temp = r[i];
r[i] = r[k];
r[k] = temp;
}
}
}
// 打印数组函数
void printArray(int arr[], int size) {
for (int i = 0; i < size; i++)
printf("%d ", arr[i]);
printf("\n");
}
// 测试示例
int main() {
int n;
printf("请输入数组元素个数:");
scanf("%d", &n);
int arr[n];
printf("请输入数组元素:\n");
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
printf("排序前的数组为:\n");
printArray(arr, n);
SelectSort(arr, n);
printf("排序后的数组为:\n");
printArray(arr, n);
return 0;
}
2. 对一组数据进行堆排序(按升序排列)。
#include <stdio.h>
#define MAX_SIZE 100
typedef struct {
int Key;
} LineList;
// 堆排序的筛选函数
void Sift(LineList r[], int low, int high) {
int i = low, j = 2 * i;
LineList tmp = r[i];
while (j <= high) {
if (j < high && r[j].Key < r[j + 1].Key)
j = j + 1;
if (tmp.Key < r[j].Key) {
r[i] = r[j];
i = j;
j = 2 * i;
} else
break;
}
r[i] = tmp;
}
// 堆排序函数
void HeapSort(LineList r[], int n) {
int i;
LineList tmp;
for (i = n / 2; i >= 1; i--)
Sift(r, i, n);
for (i = n; i >= 1; i--) {
tmp = r[1];
r[1] = r[i];
r[i] = tmp;
Sift(r, 1, i - 1);
}
}
// 打印数组函数
void printArray(LineList arr[], int size) {
for (int i = 0; i < size; i++)
printf("%d ", arr[i].Key);
printf("\n");
}
// 测试示例
int main() {
LineList arr[MAX_SIZE];
int n;
printf("请输入数组元素个数: ");
scanf("%d", &n);
printf("请输入数组元素: \n");
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i].Key);
}
printf("排序前的数组为: \n");
printArray(arr, n);
HeapSort(arr, n);
printf("排序后的数组为: \n");
printArray(arr, n);
return 0;
}
3. 对一组数据进行一趟二路归并排序(按升序排列)。
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 100
typedef struct {
int Key;
} LineList;
// 归并排序的两个相邻有序段的合并函数
void Merge(LineList r[], int low, int mid, int high) {
LineList *r1;
int i = low, j = mid + 1, k = 0;
r1 = (LineList *)malloc((high - low + 1) * sizeof(LineList));
while (i <= mid && j <= high) {
if (r[i].Key <= r[j].Key)
r1[k++] = r[i++];
else
r1[k++] = r[j++];
}
while (i <= mid)
r1[k++] = r[i++];
while (j <= high)
r1[k++] = r[j++];
for (k = 0, i = low; i <= high; k++, i++)
r[i] = r1[k];
free(r1);
}
// 打印数组函数
void printArray(LineList arr[], int size) {
for (int i = 0; i < size; i++)
printf("%d ", arr[i].Key);
printf("\n");
}
// 测试示例
int main() {
LineList arr[MAX_SIZE];
int n;
printf("请输入数组元素个数: ");
scanf("%d", &n);
printf("请输入数组元素: \n");
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i].Key);
}
printf("排序前的数组为: \n");
printArray(arr, n);
int mid = n / 2;
Merge(arr, 0, mid, n - 1);
printf("一趟二路归并排序后的数组为: \n");
printArray(arr, n);
return 0;
}
六、实训注意事项
1.题目自选,课内至少要完成两个题目。
2.若完成题目个数多或设计的算法效率高,予以加分。
七、预习与思考题
1.堆排序算法思想。
2.归并排序算法思想。
八、实训报告要求
1.书写算法或完整程序。
2. 若调试程序时出现错误,请分析错误原因并给出解决方法。