一、实验题目
常用的排序算法有冒泡排序、直接插入排序、简单选择排序、快速排序、希尔排序、堆排序等。接下来通过编程逐步分析各种排序。
二、需求分析
[问题描述]
各种内部排序算法的时间复杂度分析结果只给出了算法执行时间的阶,或大概执行时间。试通过随机的数据比较各算法的关键字比较次数和关键字移动次数,以取得直观感受。
[基本要求]
对以下常用的内部排序算法进行比较:起泡排序、直接插入排序、简单选择排序、快速排序、希尔排序、堆排序。
[测试数据]
由随机产生器决定。
[实现提示]
待排序表的表长不少于 100;其中的数据要用伪随机数产生程序产生;至少要用 5 组不同的输入数据作比较;比较的指标为有关键字参加的比较次数和关键字移动次数(关键字交 换计为 3 次移动)。
[选作内容]
对不同的输入表长做试验,观察检查两个指标相关于表长的变化关系。还可以对稳定性
做验证。
三、概要设计
运行代码:
/*彭名驹
2019.12.27
*/
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
#define Max 1000
long bj[Max], yd[Max];
typedef struct {
int key;
} Data;
long i,j,k;
void show(Data R[], long n) {
cout<<"结果为:";
for (i = 1; i <= n; i++)
cout << R[i].key << " ";
cout << endl;
}
//冒泡排序
void Maopao(Data R[], long n) {
Data m[Max], temp;
for (i = 0; i <= n; i++)
m[i] = R[i];
for (i = 1; i < n; i++)
for (j = 1; j <= n - i; j++) {
bj[1]++; //比较次数加1
if (m[j].key > m[j + 1].key) {
temp = m[j];
m[j] = m[j + 1];
m[j + 1] = temp;
yd[1] += 3; //移动次数加3
}
}
cout << "冒泡排序";
show(m, n);
}
//直接插入排序
void zhijiecharu(Data R[], long n) {
Data r[Max];
for (i = 0; i <= n; i++)
r[i] = R[i];
for (i = 2; i <= n; i++) {
bj[2]++; //比较次数加1
if (r[i].key < r[i - 1].key) { //需要将r[i]插入有序字表
r[0] = r[i];
r[i] = r[i - 1]; //r[i-1]后移
for (j = i - 2; r[0].key < r[j].key; j--)
r[j + 1] = r[j]; //记录逐个后移,直到找到插入位置
r[j + 1] = r[0];
yd[2] += 3; //循环一次移动次数加3
}
}
cout << "直接插入排序";
show(r, n);
}
//简单选择排序
void Choice(Data R[], long n) {
Data c[Max], temp;
for (i = 0; i <= n; i++)
c[i] = R[i];
for (i = 1; i <= n; i++) { //在r中选择关键字最小的记录
k = i;
for (j = i + 1; j <= n; j++) {
bj[3]++; //比较次数加1
if (c[j].key < c[k].key)
k = j; //k指向此趟关键字最小的记录
}
if (k != i) {
temp = c[k];
c[k] = c[i];
c[i] = temp;
yd[3] += 3; //移动次数加3
}
}
cout << "简单选择排序";
show(c, n);
}
//快速排序 枢纽
long Partition(Data R[], long low, long high) {
//进行一次排序,返回枢纽位置
R[0] = R[low]; //子表第一个记录做枢轴
yd[4]++; //交换次数加1
while (low < high) {
while (low < high&&R[high].key >= R[0].key) {
bj[4]++; //比较次数加1
high--;
}
if (low < high) {
R[low] = R[high];
low++;
yd[4]++; //移动次数加1
}
while (low < high&&R[low].key <= R[0].key) {
bj[4]++;
low++;
}
if (low < high) {
R[high] = R[low];
high--;
yd[4]++;
}
}
R[low] = R[0]; //枢轴记录到位
yd[4]++; //交换次数加1
return low; //返回枢轴位置
}
void Quick(Data R[], long low, long high) {
long n;
n = high - low + 1;
//low=1; high=n;
if (low < high) {
i = Partition(R, low, high);
Quick(R, low, i - 1); //左子表递归排序
Quick(R, i + 1, high); //右子表递归排序
}
}
void Quickzhanshi(Data R[], long n) {
cout << "快速排序";
show(R, n);
}
//希尔排序
void Shell(Data R[], long sh, long n) {
//对R做一趟增量是dk的希尔插入排序
for (i = sh + 1; i <= n; i++) {
bj[5]++;
if (R[i].key < R[i - sh].key) { //需要将R[i]插入有序增量子表
R[0] = R[i];
yd[5]++;
for (j = i - sh; j > 0 && (R[0].key < R[j].key); j = j - sh) {
bj[5]++;
R[j + sh] = R[j]; //寻找插入位置
yd[5]++;
}
R[j + sh] = R[0];
yd[5]++;
}
}
}
void Shell(Data R[], long n) {
Data r[Max];
long i;
for (i = 1; i <= n; i++)
r[i] = R[i];
for (long dk = n; dk >= 1; dk /= 2)
Shell(r, dk, n);
cout << "希尔排序";
show(r, n);
}
//堆调整
void DuiAdjust(Data R[], long s, long m) {
//假设R[s+1...m]已经是堆,将R[s...m]调整为以R[s]为根的大根堆
long dj;
Data dui;
dui = R[s];
for (dj = 2 * s; dj <= m; dj = 2 * dj) {
bj[6]++;
if (dj < m&&R[dj].key < R[dj + 1].key)
dj = dj + 1;
if (dui.key >= R[dj].key)
break;
R[s] = R[dj];
yd[6]++;
s = dj;
}
R[s] = dui;
}
void Duipaixu(Data R[], long n) {
Data r[Max], dui;
long i;
for (i = 1; i <= n; i++)
r[i] = R[i];
for (i = n / 2; i > 0; i--)
DuiAdjust(r, i, n);
for (i = n; i > 1; i--) {
dui = r[1];
r[1] = r[i];
r[i] = dui;
yd[6] += 3;
DuiAdjust(r, 1, i - 1);
}
cout << "堆排序";
show(r, n);
}
int main() {
long n;
Data R[Max];
cout << "数据个数为:" << endl;
cin >> n;
for (i = 1; i <= n; i++)
R[i].key = rand() % 1000; //电脑产生随机数
cout << "随机产生的数字集合为:" << endl;
for (i = 1; i <= n; i++)
cout << R[i].key << " ";
cout << endl;
Maopao(R, n); //冒泡排序
zhijiecharu(R, n); //直接插入排序
Choice(R, n); //简单选择排序
Shell(R, n); //希尔排序
Duipaixu(R, n); //堆排序
Quick(R, 0, n); //快速排序
Quickzhanshi(R,n);
cout << "结果为:" << endl;
cout << "排序方式" << "比较次数" <<"移动次数" << endl;
cout << "冒泡排序" <<bj[1] <<"\t\t" << yd[1] << endl;
cout << "直接插入排序" << bj[2] << "\t\t" << yd[2] << endl;
cout << "简单选择排序"<< bj[3] << "\t\t" << yd[3] << endl;
cout << "快速排序" << bj[4] << "\t\t" << yd[4] << endl;
cout << "希尔排序" << bj[5] << "\t\t" << yd[5] << endl;
cout << "堆排序" << bj[6] << "\t\t" << yd[6] << endl;
}
四、调试分析
调试结果如上图所示,无错误。
五、使用说明
第一步:在程序中输入产生随机数的个数
第二步:程序自动输出相应结果
六、测试结果
七、其他数据结构实例
数据结构:编程带你了解约瑟夫环
数据结构:简易停车场管理系统
数据结构:哈夫曼编/译码设计
数据结构:图的基本操作模拟-校园导游
数据结构:哈希表设计
以上内容为个人学习总结,如有遗漏或者错误请在评论区中指正!!!
如果看完觉得有所收获的话,记得一键三连哦,谢谢大家!