一、需求分析
输入10个数,编程实现插入排序、快速排序、选择排序三类算法。
二、概要设计
- 程序中用到的抽象数据类型的定义:
//定义顺序表结构
typedef struct
{
RcdType r[MAX_SIZE + 1];
// r[0] 闲置,实际存储的元素从 r[1] 开始
int length; // 顺序表的当前长度
} SqList;
- 主程序的流程:
首先指示使用者输入元素数量,将其存入list.length,并判断是否超过数组最大容量,合理则将扫描使用者输入元素,存入数组。接下来选择排序方式,再用print函数打印对应排序方式的结果。核心算法就是print函数里的三个排序算法。
// 主函数
int main()
{
SqList list; // 创建一个 SqList 实例
int i, a;
printf("请输入元素数量(不超过 %d):\n", MAX_SIZE);
scanf("%d", &list.length);
if (list.length > MAX_SIZE)
{
// 如果输入的 list.length 值超过了数组的最大大小
//输出错误信息并退出
printf("错误:输入的数量超过了最大限制。\n");
return 1;
}
printf("请输入 %d 个元素:\n", list.length);
for (i = 1; i <= list.length; i++) { // 修改为从1开始以适应我们的存储方案
scanf("%d", &list.r[i]);
}
printf("请选择排序方式:1.插入排序;2.快速排序;3.选择排序\n请输入序号(如1):");
scanf("%d", &a);
print(&list, a); // 修改为传递 SqList 对象的地址和排序选项
return 0;
}
三、详细设计
- 插入排序
// 插入排序
void insertionSort(SqList *list)
{
int i, j;
RcdType key;
for (i = 2; i <= list->length; i++)
{
list->r[0] = list->r[i]; //r[0]为监视哨
j = i - 1;
while (list->r[j] > list->r[0])
{
list->r[j + 1] = list->r[j];
j--;
}
list->r[j + 1] = list->r[0];
}
}
- 快速排序
// 快速排序的辅助函数
int partition(SqList *list, int low, int high)
{
int pivot = list->r[high];
int i = (low - 1);
for (int j = low; j < high; j++)
{
if (list->r[j] < pivot)
{
i++;
// 交换 list->r[i] 和 list->r[j]
RcdType temp = list->r[i];
list->r[i] = list->r[j];
list->r[j] = temp;
}
}
RcdType temp = list->r[i + 1];
list->r[i + 1] = list->r[high];
list->r[high] = temp;
return (i + 1);
}
// 快速排序
void quickSort(SqList *list, int low, int high)
{
if (low < high)
{
int pi = partition(list, low, high);
quickSort(list, low, pi - 1);
quickSort(list, pi + 1, high);
}
}
- 选择排序
// 选择排序
void selectionSort(SqList *list)
{
int i, j, min_idx;
for (i = 1; i <= list->length - 1; i++)
{
min_idx = i;
for (j = i + 1; j <= list->length; j++)
if (list->r[j] < list->r[min_idx])
min_idx = j;
RcdType temp = list->r[min_idx];
list->r[min_idx] = list->r[i];
list->r[i] = temp;
}
}
- 打印函数
在打印函数中使用switch调用各个排序方式。
//排序方式
void print(SqList *list, int a)
{
switch (a)
{
case 1:
// 调用插入排序
insertionSort(list);
printf("插入排序结果: \n");
break;
case 2:
// 调用快速排序
quickSort(list, 1, list->length);
printf("快速排序结果: \n");
break;
case 3:
// 调用选择排序
selectionSort(list);
printf("选择排序结果: \n");
break;
default:
printf("\n错误:无效的排序方式序号。\n");
return;
}
// 打印排序后的列表
for (int i = 1; i <= list->length; i++)
printf("%d ", list->r[i]);
printf("\n");
}
四、调试分析
一开始我是将三个排序方式顺序放置,但发现经过第一个排序方式,数组已经变为有序,如果要进行下面的排序,需要重新初始化数组。这时候我有两个选择,一个是使用三个数组保存输入,分别用三个数组排序,另一个选择就是只进行一次排序。我选择了第二种,第一种较为简单,直接建立两个数组,令其等于list即可。
五、测试结果
输入:49 38 65 97 49 13 27 76 22 19
输出:
- 插入排序
- 快速排序
- 选择排序
附录
#include <stdio.h>
#define MAX_SIZE 100 // 定义数组的最大大小
// 定义记录类型,这里暂且认为数组只处理整数类型。
// 如果需要处理其他类型,需要相应地修改 RcdType 的定义。
typedef int RcdType;
// 定义顺序表结构
typedef struct
{
RcdType r[MAX_SIZE + 1];
// r[0] 闲置,实际存储的元素从 r[1] 开始
int length; // 顺序表的当前长度
} SqList;
// 插入排序
void insertionSort(SqList *list)
{
int i, j;
RcdType key;
for (i = 2; i <= list->length; i++)
{
list->r[0] = list->r[i]; //r[0]为监视哨
j = i - 1;
while (list->r[j] > list->r[0])
{
list->r[j + 1] = list->r[j];
j--;
}
list->r[j + 1] = list->r[0];
}
}
// 快速排序的辅助函数
int partition(SqList *list, int low, int high)
{
int pivot = list->r[high];
int i = (low - 1);
for (int j = low; j < high; j++)
{
if (list->r[j] < pivot)
{
i++;
// 交换 list->r[i] 和 list->r[j]
RcdType temp = list->r[i];
list->r[i] = list->r[j];
list->r[j] = temp;
}
}
RcdType temp = list->r[i + 1];
list->r[i + 1] = list->r[high];
list->r[high] = temp;
return (i + 1);
}
// 快速排序
void quickSort(SqList *list, int low, int high)
{
if (low < high)
{
int pi = partition(list, low, high);
quickSort(list, low, pi - 1);
quickSort(list, pi + 1, high);
}
}
// 选择排序
void selectionSort(SqList *list)
{
int i, j, min_idx;
for (i = 1; i <= list->length - 1; i++)
{
min_idx = i;
for (j = i + 1; j <= list->length; j++)
if (list->r[j] < list->r[min_idx])
min_idx = j;
RcdType temp = list->r[min_idx];
list->r[min_idx] = list->r[i];
list->r[i] = temp;
}
}
//排序方式
void print(SqList *list, int a)
{
switch (a)
{
case 1:
// 调用插入排序
insertionSort(list);
printf("插入排序结果: \n");
break;
case 2:
// 调用快速排序
quickSort(list, 1, list->length);
printf("快速排序结果: \n");
break;
case 3:
// 调用选择排序
selectionSort(list);
printf("选择排序结果: \n");
break;
default:
printf("\n错误:无效的排序方式序号。\n");
return;
}
// 打印排序后的列表
for (int i = 1; i <= list->length; i++)
printf("%d ", list->r[i]);
printf("\n");
}
// 主函数
int main()
{
SqList list; // 创建一个 SqList 实例
int i, a;
printf("请输入元素数量(不超过 %d):\n", MAX_SIZE);
scanf("%d", &list.length);
if (list.length > MAX_SIZE)
{
// 如果输入的 list.length 值超过了数组的最大大小
//输出错误信息并退出
printf("错误:输入的数量超过了最大限制。\n");
return 1;
}
printf("请输入 %d 个元素:\n", list.length);
for (i = 1; i <= list.length; i++)
{ // 修改为从1开始以适应我们的存储方案
scanf("%d", &list.r[i]);
}
printf("请选择排序方式:1.插入排序;2.快速排序;3.选择排序\n请输入序号(如1):");
scanf("%d", &a);
print(&list, a); // 修改为传递 SqList 对象的地址和排序选项
return 0;
}