题目:
使用简单数组实现下面各种排序算法,并进行比较。
排序算法:
1、插入排序
2、希尔排序
3、冒泡排序
4、快速排序
5、简单选择排序
6、堆排序(选作)
7、归并排序(选作)
8、基数排序(选作)
9、其他
要求:
1、测试数据分成三类:正序、逆序、随机数据
2、对于这三类数据,比较上述排序算法中关键字的比较次数和移动次数(其中关键字交换计为3次移动)。
3、对于这三类数据,比较上述排序算法中不同算法的执行时间,精确到微秒(选作)
4、对2和3的结果进行分析,验证上述各种算法的时间复杂度
编写测试main()函数测试线性表的正确性。
需求分析:
(1)输入的形式:整形数组,且需要把整形数组的第一个元素空出来。
(2)输出的形式:也为整形数组,且是被从小到大排序过后的整形数组,并输出每种排
序成功前所需用到的比较次数、移动次数。
(3)程序所能达到的功能:将用户输入的数组进行排序,并输出每种排序方式所需要的
比较次数和移动次数。
(4)测试数据:正确输入: 7 6 5 4 3 2 1
正确输出:1 2 3 4 5 6 7
直接插入排序比较次数:27
直接插入排序移动次数:33
1 2 3 4 5 6 7
希尔排序比较次数:17
希尔排序移动次数:19
1 2 3 4 5 6 7
冒泡排序的比较次数:21
冒泡排序的移动次数:63
1 2 3 4 5 6 7
快速排序的比较次数:21
快速排序的移动次数:18
1 2 3 4 5 6 7
简单排序的比较次数:21
简单排序的移动次数:9
详细设计:
Main:定义数组,输入数据,调用函数;
InsertSort: 对main函数中传过来的数组进行直接插入排序:
(1)用n-1趟循环将数组r[]中较大的数存在r[0]中,移动次数加一;
(2)用另一个内层循环将r[]中的数与r[0]比较,并在查找的过程中边查找边
后移;移动次数和比较次数均加一。
(3)在较外层的比较后增加比较次数。
(4)用一次循环从1到n将排序后的r输出。
(5)输出直接插入排序的比较次数和移动次数。
ShellInsert:对main函数中传过来的数组进行希尔排序:
(1)以d为增量将原数组分组;
(2)在d+1到n之间进行一趟希尔排序:
(2.1) 在每次“一趟希尔排序”中,将每组的较大数存在r[0]中,移动次数加一,比较次数加一;
(2.2) 用循环从后往前将数组中的数与r[0]比较,并把较大的数向后移,以d为增量变换。移动次数加一,比较次数加一。
(2.3) 最后将r[0]存在最后的循环停止位置,移动次数加一。
(3)用一次循环从1到n将排序后的r[]输出。
(4)输出希尔排序的比较次数和移动次数。
BubbleSort:对main函数中传过来的数组进行冒泡排序:
(1)用n设置初始化时无序元素的范围。
(2)用for循环在每趟排序的无序元素范围内进行相邻元素的比较;若前一
个元素大于后一个元素,则将两个数进行交换,并重置无序元素的范
围,使下一次排序的无序元素范围减小。移动次数加3,比较次数加
一。
(3)在无序元素范围不为0的时候,再次进行第二步。
(4)用一次循环从1到n将排序后的r[]输出。
(5)输出冒泡排序的比较次数和移动次数。
QSort:对main函数中传过来的数组进行快速排序:
(1)用i和j设置快速排序的左右分区;
(2)在左右分区依然存在的情况下,调用Partion进行一次快排,并得到一次快排后的新的分区分界值。
(3)通过递归的方式再次在新的分区中进行快速排序。
Partion:对QSort函数中传过来的数组在其所指定的分区中进行快速排序一趟排序:
(1)通过Partion的传递参数中确定一趟排序所需的分区的左界和右界,并保存
第一个元素作为基准元素。
(2)在分区内依然有元素的情况下,先从右侧扫描,寻找小于基准元素的数并将其前移,比较次数加一。
(3)将基准元素存在右侧扫描结束的地方,移动次数加一。
(4)再左侧扫描,寻找大于或等于基准元素的数并将其后移,比较次数加一。
(5)一次排序基本结束,将轴值移动至i=j的位置,移动次数加一,并返回分区的分界值。
cQ:
(1)调用QSort;
(2)用一次循环从1到n将排序后的r[]输出。
(3)输出快速排序的比较次数和移动次数。
Selectsort:对main函数中传过来的数组进行排序:
(1)在n-1趟循环中,用index记录查找的最小位置。
(2)在内层循环中,若某个位置的数值小于index位置处的数值,则将此位置记录为新的index,并使比较次数加一。
(3)若第一个就是最小元素,则不用交换;若第一个不是最小元素,则利用r[0]作为临时空间交换记录,将查找到的该位置的数值与index处的数值交换。移动次数加三。
(4)用一次循环从1到n将排序后的r[]输出。
(5)输出简单排序的比较次数和移动次数。
调试分析:
这次实验的主要难点是比较和移动的次数的计数。但是只要对代码有一定的了解和掌握,就可以成功。
用户使用说明:
输入的必须是整形数,若需要改变所需排序数组的元素个数,则需要改变main函数代码对应位置。
测试结果:
输入:5 2 4 6 3 1 7
输出:1 2 3 4 5 6 7
直接插入排序比较次数:16
直接插入排序移动次数:18
1 2 3 4 5 6 7
希尔排序比较次数:18
希尔排序移动次数:18
1 2 3 4 5 6 7
冒泡排序的比较次数:16
冒泡排序的移动次数:30
1 2 3 4 5 6 7
快速排序的比较次数:13
快速排序的移动次数:17
1 2 3 4 5 6 7
简单排序的比较次数:21
简单排序的移动次数:12
主程序:
/*
使用简单数组实现下面各种排序算法,并进行比较。
排序算法:
1、插入排序
2、希尔排序
3、冒泡排序
4、快速排序
5、简单选择排序
6、堆排序(选作)
7、归并排序(选作)
8、基数排序(选作)
9、其他
2018.06.06 created by Cheng Zixin
*/
#include<iostream>
using namespace std;
static int com = 0, mov = 0;
void InsertSort(int r[], int n)
{
int m=0,compare1=0,move1=0;
for (int i = 2; i <= n; i++) //i从2~n循环,共n-1趟排序
{
if (r[i] < r[i - 1])
{
r[0] = r[i]; move1++;
for (int j = i - 1; r[0] < r[j]; j--) //边查找边后移
{
r[j + 1] = r[j]; m = j;
/*for (int p = 1; p <= n; p++)
cout << r[p] << " ";
cout << "又一次" << endl;*/
move1++,compare1++;
}
r[m] = r[0]; move1++;
}
compare1++;
}
for (int i = 1; i <= n; i++)
cout << r[i]<<" ";
cout << endl;
cout << "直接插入排序比较次数:" << compare1 << endl;
cout << "直接插入排序移动次数:" << move1 << endl;
}
//希尔排序
void ShellInsert(int r[], int n)
{
int compare2 = 0,move2=0;
for (int d = n / 2; d >= 1; d = d / 2) //以d为增量
{
for (int i = d + 1; i <= n; i++) //一趟希尔排序
{
if (r[i] < r[i - d])
{
int m;
r[0] = r[i]; move2++;
for (int j = i - d; j > 0 && r[0] < r[j]; j = j - d)
{
r[j + d] = r[j]; m = j;
compare2++; move2++;
}
r[m] = r[0]; move2++;
}
compare2++;
}
}
for (int i = 1; i <= n; i++)
cout << r[i] << " ";
cout << endl;
cout << "希尔排序比较次数:" << compare2 << endl;
cout << "希尔排序移动次数:" << move2 << endl;
}
//冒泡排序(改进)
void BubbleSort(int r[], int n)
{
int compare3 = 0, move3 = 0;
int pos = n; //初始化时无序元素的范围
while (pos != 0)
{
int bound = pos; //本趟排序无序元素的范围
pos = 0;
for (int i = 1; i < bound; i++)
{
if (r[i] > r[i + 1]) //相邻元素比较
{
r[0] = r[i]; r[i] = r[i + 1]; r[i + 1] = r[0];//交换
pos = i; move3 = move3 + 3;
}
compare3++;
}
}
for(int i=1;i<=n;i++)
cout << r[i] << " ";
cout << endl;
cout << "冒泡排序的比较次数:" << compare3 << endl;
cout << "冒泡排序的移动次数:" << move3 << endl;
}
//快速排序
int Partion(int r[], int first, int end) //快速排序一趟排序
{
int i = first; //分区的左界
int j = end; //分区的右界
int pivot = r[i]; //保存第一个元素,作为基准元素
while (i < j)
{
while ((i < j) && (r[j] >= pivot)) //右侧扫描,寻找<pivot的元素前移
j--,com=com+1;
r[i] = r[j]; mov++;
while ((i < j) && (r[i] <= pivot)) //左侧扫描,寻找>=pivot的元素后移
i++,com=com+1;
r[j] = r[i]; mov++;
}
r[i] = pivot; mov++; //将轴值移动至i=j的位置
return i; //返回分区的分界值i
}
void Qsort(int r[], int i, int j)
{
if (i < j)
{
int pivotloc = Partion(r, i, j);
Qsort(r, i, pivotloc - 1); //左分区快速排序
Qsort(r, pivotloc + 1, j); //右分区快速排序
}
}
void cQ(int r[], int n)
{
Qsort(r, 1, n);
for (int m = 1; m <= n; m++)
cout << r[m] << " ";
cout << endl;
cout << "快速排序的比较次数:"<<com<<endl;
cout << "快速排序的移动次数:"<<mov<<endl;
}
//完整简单选择排序
void Selectsort(int r[], int n)
{
int compare4 = 0, move4 = 0;
for (int i = 1; i < n; i++) //n-1趟排序
{
int index = i; //查找最小位置的记录index
for (int j = i + 1; j <= n; j++)
{
if (r[j] < r[index])
index = j;
compare4++;
}
if (index != i) //若第一个就是最小元素,则不用交换
{
r[0] = r[i];
r[i] = r[index];
r[index] = r[0]; //利用r[0]作为临时空间交换记录
move4 = move4 + 3;
}
}
for (int i =1 ; i <=n; i++)
cout << r[i] << " ";
cout << endl;
cout << "简单排序的比较次数:" <<compare4<< endl;
cout << "简单排序的移动次数:" <<move4<< endl;
}
int main()
{
int r[8];
r[0] = 0;
for (int i = 1; i < 8; i++)
cin >> r[i];
int a[8] = { 0 }, b[8] = { 0 }, c[8] = { 0 }, d[8] = { 0 };
for (int i = 0; i < 8; i++)
{
a[i] = b[i] = c[i] = d[i] = r[i];
}
//int r[8] = { 0,7,6,5,4,3,2,1};
//int r[8] = {0,12,15,9,20,10,31,24};
InsertSort(r, 7);
ShellInsert(a,7);
BubbleSort(b, 7);
cQ(c, 7);
Selectsort(d, 7);
system("pause");
return 0;
}
如果对您有帮助,请点赞+评论~