一、 实验目的
1. 掌握各种常用排序的算法思想;
2. 掌握各种常用排序的算法实现;
3. 掌握各种常用排序时间复杂度,比较各种排序的优缺点。
二.排序算法的归类:
总的排序算法分为以下几类:1.插入类排序:如:直接插入排序,折半插入排序,希尔排序
2.交换类排序:如:冒泡排序,快速排序,其中冒泡排序应该是计算机专业的学生最为熟悉的一种排序算法了,而快速排序则是在冒泡排序的基础上一次消除多个逆序对改进而来3.选择类排序:如:简单选择排序,堆排序。
4.其它类排序:如:归并排序,基数排序等。
三、 实验内容与要求
1. 编程实现各种排序算法,并对比各种算法的效率。
【设计要求】在给出的代码素材sort.cpp文件中补充main函数中的swtich语句,以及以下排序函数,并比较各种排序方法在对素材文件中的1.data~5.data待排序序列进行排序时所需要的时间。
void shellsort(int data[],int n);//希尔排序
void bubllesort(int data[],int n);//冒泡排序
void quicksort(int data[],int n);//快速排序
void selectsort(int data[],int n);//简单选择排序
void heapsort(int data[],int n);//堆排序
void mergesort(int data[],int n);//合并排序
void radixsort(int data[],int n) ;//基数排序
2.【程序代码】完成createdata函数及排序函数,其中createdata可参考下图,其中往目标文件中写入两部分内容,随机数的总个数及产生各个随机数。
方法一:C++版
1. sort.h
#include<iostream>
#include<fstream>
#include<stdlib.h>
using namespace std;
const int LineLenght=20;//控制屏幕打印时,每行元素个数
class sort
{
private:
int *data,n;
public:
void Printdata();
void Getdata(string file);
void creatdata(int num);
void Outputdata();
void insertsort();//直接插入排序
void shellsort();//希尔排序
void bubllesort();//冒泡排序
void quicksort(int low, int high);//快速排序
void selectsort();//简单选择排序
void heapsort();//堆排序
void sift(int start,int endnode);
void mergesort();//合并排序
void merge(int low, int high,int temp[]);
void radixsort();//基数排序
};
2. sort.cpp
#include<iostream>
#include<fstream>
#include<stdlib.h>
#include"sort.h"
using namespace std;
//======打印=============================================================
void sort::Printdata( )
{
for(int i=1;i<=n;i++)
{
cout<<data[i]<<" ";
if(i%LineLenght==LineLenght-1)
cout<<endl;
}
cout<<endl;
}
//========读取数据=========================================================
void sort::Getdata(string file)
{
ifstream read(file);
if (!read)
{
cout << "\n\t文件读取错误!!!\n\n"; system("pause");
}
else
{
read>>n;
data = new int[n + 1];
for(int i=1;i<=n;i++)
read>>data[i];
}
read.close();
}
//========生成随机数据=====================================================
void sort::creatdata(int num)
{
ofstream write("in.txt");
write<<num<<endl;
for(int i=0;i<num;i++)
{
write<<rand()%1000+1<<" ";
}
write.close();
}
//========写出排序后的数据=================================================
void sort::Outputdata( )
{
ofstream write("out.txt");
write<<n<<endl;
for(int i=1;i<=n;i++)
{
write<<data[i]<<" ";
}
}
//=========================排序方法======================================
//========直接插入排序=====================================================
void sort::insertsort()
{
for (int i = 2; i <= n; i++)
{
data[0] = data[i];
int j;
for (j = i - 1; j>0 && data[0] < data[j]; j--)
data[j + 1] = data[j];
data[j+1] = data[0];
}
}
//=======希尔排序==========================================================
void sort::shellsort()
{
for (int d=n/2; d>0; d/=2)
{
for (int i = 1 + d; i <= n; i++)
{
data[0] = data[i];
int j;
for (j = i - d; j>0 && data[0] < data[j]; j -= d)
data[j + d] = data[j];
data[j + d] = data[0];
}
}
}
//======冒泡排序===========================================================
void sort::bubllesort()
{
int flag=1;
for (int i = 1; i <= n&&flag; i++)
{
flag = 0;
for (int j = 1; j <= n-i; j++)
{
if (data[j] > data[j + 1])
{
int temp = data[j+1];
data[j + 1] = data[j];
data[j] = temp;
flag = 1;
}
}
}
}
//====快速排序=============================================================
void sort::quicksort(int low,int high)
{
int i = low, j = high;
if (low>high)
return;
data[0] = data[low];
while (i != j)
{
while (data[j] >= data[0] && i < j)
j--;
while (data[i] <= data[0] && i < j)
i++;
if (i < j)
{
int temp = data[i];
data[i] = data[j];
data[j] = temp;
}
}
data[low] = data[i];
data[i] = data[0];
quicksort(low, i - 1);//左
quicksort(i + 1, high);//右
}
//==========简单选择排序===================================================
void sort::selectsort()
{
for (int i = 1; i <= n; i++)
{
int min = i;
data[0] = data[i];
for (int j = i + 1; j <= n; j++)
{
if (data[j] < data[min])
min = j;
}
if (min != i)
{
data[i] = data[min];
data[min] = data[0];
}
}
}
//================堆排序===================================================
void sort::heapsort()
{
for (int i = n / 2-1; i >= 1; i--)
sift(i,n);
for (int i = n; i > 1; i--)
{
data[0] = data[1];
data[1] = data[i];
data[i] = data[0];
sift(1,i-1);
}
}
void sort::sift(int start,int end)
{
data[0] = data[start];
int sonode = 2 * start;
while (sonode <= end)
{
if (sonode + 1 <= end&&data[sonode + 1] > data[sonode])
sonode++;
if (data[sonode] <= data[0]) break;
data[start] = data[sonode];
start = sonode;
sonode = 2 * start;
}
data[start] = data[0];
}
//============归并排序=====================================================
void sort::merge(int low, int high,int temp[])
{
if (high <= low)
return;
int mid = (high +low) / 2;
merge(low, mid,temp);
merge(mid+1, high,temp);
int i = low, j = mid + 1;
for (int k = low; k <= high; k++)
temp[k] = data[k];
for (int k = low; k <= high; k++)
{
if (i > mid)
data[k] = temp[j++];
else if (j > high)
data[k] = temp[i++];
else if (temp[i] <= temp[j])
data[k] = temp[i++];
else
data[k] = temp[j++];
}
}
void sort::mergesort()
{
int *temp = new int[n + 1];//辅助数组
merge( 1 , n, temp);
}
//===========基数排序======================================================
void sort::radixsort()
{
int maxbit=4;//最大位数为4
int *temp = new int[n + 1];
int count[10];
int radix = 1;
for (int i = 0; i < maxbit; i++)
{
for (int j = 0; j < 10; j++)
count[j] = 0;
for (int j = 1; j <= n; j++)
{
int bit = (data[j] / radix) % 10;
count[bit]++;
}
for (int j = 1; j < 10; j++)
count[j] = count[j - 1] + count[j];
for (int j = n; j > 0; j--) //将所有桶中记录依次收集到temp中
{
int bit = (data[j] / radix) % 10;
temp[count[bit]] = data[j];
count[bit]--;
}
for (int j = 1; j <= n; j++) //将temp数组的内容复制到data中
data[j] = temp[j];
radix = radix * 10;
}
}
3. main.cpp
#include<iostream>
#include<fstream>
#include<stdlib.h>
#include<time.h>
#include"sort.h"
using namespace std;
int menu();
void carte( sort Sort,int choice,string file,int n);
void print( sort Sort,int time);
void choicefile(string &file,int &n);
void main()
{
srand((unsigned int)(time(NULL)));
int choice,n = 10000;
string file;
sort Sort;
Sort.creatdata(n);
choicefile(file, n);
do{
choice=menu();
carte(Sort, choice,file,n);
} while (choice != 0);
}
int menu()
{
int choice;
cout << "0. 退出\n1. 直接插入排序\n2. 希尔插排序\n3. 冒泡排序\n4. 快速排序\n5. 简单选择插入排序\n6. 堆排序\n7. 归并排序\n8. 基数排序\n";
cout << endl << "请选择排序方式:"; cin >> choice;
return choice;
}
void print(sort Sort,int time)
{
Sort.Printdata();//打印
Sort.Outputdata();//写出
cout << "排序时间为" <<time << "毫秒" << endl;
cout << "您可以尝试一下其它的排序方法:\n";
}
void carte(sort Sort,int choice,string file,int n)
{
clock_t start, end;
switch (choice)
{
case 0:break;
case 1:{
system("cls");
Sort.Getdata(file);//读取
start = clock();
Sort.insertsort();//排序
end = clock();
print(Sort, end - start); }
break;
case 2:{
system("cls");
Sort.Getdata(file);
start = clock();
Sort.shellsort();
end = clock();
print(Sort, end - start); }
break;
case 3:{
system("cls");
Sort.Getdata(file);
start = clock();
Sort.bubllesort();
end = clock();
print(Sort, end - start); }
break;
case 4:{
system("cls");
Sort.Getdata(file);
start = clock();
Sort.quicksort(1, n);
end = clock();
print(Sort, end - start); }
break;
case 5:{
system("cls");
Sort.Getdata(file);
start = clock();
Sort.selectsort();
end = clock();
print(Sort, end - start); }
break;
case 6:{
system("cls");
Sort.Getdata(file);
start = clock();
Sort.heapsort();
end = clock();
print(Sort, end - start); }
break;
case 7:{
system("cls");
Sort.Getdata(file);
start = clock();
Sort.mergesort();
end = clock();
print(Sort, end - start); }
break;
case 8:{
system("cls");
Sort.Getdata(file);
start = clock();
Sort.radixsort();
end = clock();
print(Sort, end - start); }
break;
default:
cout << "没有这种排序方式,请选择正确的排序方法:\n\n";
}
}
void choicefile(string &file,int &n)
{
int choice;
ifstream in;
cout << "选择排序文件:\n";
cout << "\t1. in.txt\n\t2. 1.txt\n\t3. 2.txt\n";
cin >> choice;
switch (choice)
{
case 1:file = "in.txt"; break;
case 2:file = "1.txt";
in.open(file,ios::beg);
in >> n;
in.close();break;
case 3:file = "2.txt";
in.open(file,ios::beg);
in >> n;
in.close(); break;
default:cout << "\n\t找不到文件!!!\n\n"; system("pause");
}
system("cls");
}
#include "sort.h"方法二:C版
1. sort.h
素材包含,此处略
2. sort.cpp
#include <algorithm>
#include <string.h>
void Printdata(int data[],int n)
{
for(int i=0;i<n;i++)
{
printf("%4d",data[i]);
if(i%LineLenght==LineLenght-1)
printf("\n");
}
printf("\n");
return;
}
int Getdata(int data[], int &n)
{
FILE *fp;
if ((fp = fopen(SOURCEFILE,"r")) == NULL) /* 以读方式打开文本文件 */
{
printf("Failure to open score.txt!\n");
return 0;//读数据失败
}
int i=0;
fscanf(fp,"%6d",&n);//获取文件中的元素个数
while(!feof(fp)&&i<n)
{
fscanf(fp,"%10d",&data[i]);
i++;
}
fclose(fp);
return 1; //成功读数据
}
void insertsort(int data[], int n)//直接插入排序
{
for(int i = 1, j; i < n; i++) {
int x = data[i];
for(j = i-1; j >= 0; j--) {
if(data[j] > x)
data[j+1] = data[j];
else break;
}
if(j != i) data[j+1] = x;
}
}
void creatdata(int &n)
{
FILE *p;
p = fopen(SOURCEFILE, "w");
srand((unsigned)time(NULL));
if (p == NULL) {
printf("创建文件失败!");
} else {
fprintf(p, "%6d", n);
for (int i = 0; i < n; i++) {
int num = rand() % 1000 + 1;
fprintf(p, "%10d", num);
}
fclose(p);
}
}
int Outputdata(int data[],int n)
{
FILE *fp;
if ((fp = fopen("out.txt","w")) == NULL) /* 以写方式打开文本文件 */
{
printf("Failure to open score.txt!\n");
return 0;//写数据失败
}
for(int i=0;i<n;i++)
fprintf(fp,"%10d",data[i]);
fclose(fp);
return 1;
}
void shellsort(int data[],int n)//希尔排序
{
for (int gap = n / 2; gap > 0; gap /= 2) {
for (int i = 0; i < gap; i++) {
for (int j = i + gap; j < n; j += gap) {
if (data[j] < data[j-gap]) {
int temp = data[j], k = j - gap;
while (k >= 0 && data[k] > temp) {
data[k + gap] = data[k];
k -= gap;
}
data[k + gap] = temp;
}
}
}
}
}
void bubllesort(int data[],int n)//冒泡排序
{
for (int i = 0; i < n; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (data[j] > data[j+1]) {
std::swap(data[j+1], data[j]);
}
}
}
}
void quicksort(int data[], int n, int low, int high) //快速排序
{
if (low < high) {
int temp = data[low], l = low, r = high-1;
while (l < r) {
while (l < r && data[r] > temp) r--;
if (l < r)
data[l++] = data[r];
while (l < r && data[l] < temp) l++;
if (l < r)
data[r--] = data[l];
}
data[l] = temp;
quicksort(data, n, low, l-1);
quicksort(data, n, l+1, high);
}
}
void selectsort(int data[],int n)//简单选择排序
{
for (int i = 0; i < n; i++) {
int index = i;
for (int j = i + 1; j < n; j++) {
if (data[j] > data[index]) {
index = j;
}
}
if (index != i) std::swap(data[index], data[i]);
}
}
void heapAdjustDown(int *arr, int start, int end) {
int temp = arr[start];
int i = 2 * start + 1;
while (i <= end) {
if (i + 1 <= end && arr[i + 1] > arr[i]) i++;
if (arr[i] <= temp) break;
arr[start] = arr[i];
start = i;
i = 2 * start + 1;
}
arr[start] = temp;
}
void heapsort(int data[],int n)//堆排序
{
for (int i = n / 2 - 1; i >= 0; i--) {
heapAdjustDown(data, i, n - 1);
}
for (int i = n - 1; i > 0; i--) {
std::swap(data[i], data[0]);
heapAdjustDown(data, 0, i - 1);
}
}
void merge(int *data, int start, int end, int *result) {
int left_length = (end - start + 1) / 2 + 1;
int left_index = start;
int right_index = start + left_length;
int result_index = start;
while (left_index < start + left_length && right_index < end + 1) {
if (data[left_index] <= data[right_index])
result[result_index++] = data[left_index++];
else
result[result_index++] = data[right_index++];
}
while (left_index < start + left_length)
result[result_index++] = data[left_index++];
while (right_index < end + 1)
result[result_index++] = data[right_index++];
}
void mergesort(int data[], int start, int end, int *result) //合并排序
{
/*for (int i = 0; i < 10; i++)
printf("%d ", data[i]);
puts("");*/
if (end - start == 1) {
if (data[start] > data[end]) std::swap(data[start], data[end]);
return;
}
else if (end == start) return;
else {
mergesort(data, start, (end-start+1)/2+start, result);
mergesort(data, (end - start + 1) / 2 + start+1, end, result);
merge(data, start, end, result);
for (int i = start; i <= end; i++) {
data[i] = result[i];
}
}
}
int maxbit(int data[], int n) //确定基数排序的关键字个数
{
int d = 1, p = 10;
for (int i = 0; i < n; i++) {
while (data[i] >= p) {
p *= 10;
++d;
}
}
return d;
}
void radixsort(int data[], int n)//基数排序
{
int d = maxbit(data, n);
int temp[MaxSize], count[10], radix = 1;
for (int i = 1; i <= d; i++) {
memset(count, 0, sizeof(count));
for (int j = 0; j < n; j++) {
int k = (data[j] / radix) % 10;
count[k]++;
}
for (int j = 1; j < 10; j++) {
count[j] += count[j - 1];
}
for (int j = n - 1; j >= 0; j--) {
int k = (data[j] / radix) % 10;
temp[count[k] - 1] = data[j];
count[k]--;
}
for (int j = 0; j < n; j++) {
data[j] = temp[j];
}
radix *= 10;
}
}
3. main.cpp
#include "sort.h"
int main()
{
int n=10;
int data[MaxSize];
clock_t start,end;
creatdata(n);
Getdata( data, n); //读取文件的数据存放在data数组中
int menu;
printf("请选择排序方式:\n");
while(1) {
printf("1. 直接插入排序\n");
printf("2. 希尔插排序\n");
printf("3. 冒泡排序\n");
printf("4. 快速排序\n");
printf("5. 简单选择插入排序\n");
printf("6. 堆排序\n");
printf("7. 归并排序\n");
printf("8. 基数排序\n");
scanf("%d",&menu);
switch(menu)
{
case 1:{
start = clock();
insertsort(data, n);
end = clock();
Printdata(data ,n);//在屏幕上输出数据
Outputdata(data ,n);//输出至文件
printf("排序时间为%d毫秒",end-start);
printf("您可以尝试一下其它的排序方法:\n");
break;
}
case 2 : {
start = clock();
shellsort(data, n);
end = clock();
Printdata(data ,n);//在屏幕上输出数据
Outputdata(data ,n);//输出至文件
printf("排序时间为%d毫秒",end-start);
printf("您可以尝试一下其它的排序方法:\n");
break;
}
case 3 : {
start = clock();
bubllesort(data, n);
end = clock();
Printdata(data ,n);
Outputdata(data ,n);
printf("排序时间为%d毫秒",end-start);
printf("您可以尝试一下其它的排序方法:\n");
break;
}
case 4 : {
start = clock();
quicksort(data, n, 0, n);
end = clock();
Printdata(data ,n);
Outputdata(data ,n);
printf("排序时间为%d毫秒",end-start);
printf("您可以尝试一下其它的排序方法:\n");
break;
}
case 5: {
start = clock();
selectsort(data, n);
end = clock();
Printdata(data, n);
Outputdata(data, n);
printf("排序时间为%d毫秒", end - start);
printf("您可以尝试一下其它的排序方法:\n");
break;
}
case 6: {
start = clock();
heapsort(data, n);
end = clock();
Printdata(data, n);
Outputdata(data, n);
printf("排序时间为%d毫秒", end - start);
printf("您可以尝试一下其它的排序方法:\n");
break;
}
case 7: {
start = clock();
int result[MaxSize];
mergesort(data, 0, n-1, result);
end = clock();
Printdata(result, n);
Outputdata(result, n);
printf("排序时间为%d毫秒", end - start);
printf("您可以尝试一下其它的排序方法:\n");
break;
}
case 8: {
start = clock();
radixsort(data, n);
end = clock();
Printdata(data, n);
Outputdata(data, n);
printf("排序时间为%d毫秒", end - start);
printf("您可以尝试一下其它的排序方法:\n");
break;
}
default: {
printf("没有这种排序方式,请选择正确的排序方法:\n");
}
}
}
return 0;
}
来源:CSDN
作者:芥末酱油大闸蟹
链接:https://blog.csdn.net/weixin_42442713/article/details/80959343