数据结构排序算法(一):排序方法分类和各种排序方法的实现

大兔子大兔子 提交于 2019-12-07 22:05:22

一、 实验目的

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;
}



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!