各种排序算法练习

Posted 禾小白

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了各种排序算法练习相关的知识,希望对你有一定的参考价值。

最近忙着准备找工作,把之前写的排序算法整理下,写到一起,方便以后用,废话不说,直接上代码;

#include<iostream>
#include<time.h>
using namespace std;
#define N 100
//#define SWAP(x,y){int t;t=x;x=y;y=t;}
#define SWAP(x,y) {x=x^y;y=x^y;x=x^y;}
//基数排序
void radixsort(int data[], int n) 
{
	//辅助函数,求数据的最大位数
	int d = 1; //保存最大的位数
    int p = 10;
    for(int i = 0; i < n; ++i)
    {
        while(data[i] >= p)
        {
            p *= 10;
            ++d;
        }
    }

	//基数排序
    int *tmp = new int[n];
    int *count = new int[10]; //计数器
    int i, j, k;
    int radix = 1;
    for(i = 1; i <= d; i++) //进行d次排序
    {
        for(j = 0; j < 10; j++)
            count[j] = 0; //每次分配前清空计数器
        for(j = 0; j < n; j++)
        {
            k = (data[j] / radix) % 10; //统计每个桶中的记录数
            count[k]++;
        }
        for(j = 1; j < 10; j++)
            count[j] = count[j - 1] + count[j]; //将tmp中的位置依次分配给每个桶
        for(j = n - 1; j >= 0; j--) //将所有桶中记录依次收集到tmp中
        {
            k = (data[j] / radix) % 10;
            tmp[count[k] - 1] = data[j];
            count[k]--;
        }
        for(j = 0; j < n; j++) //将临时数组的内容复制到data中
            data[j] = tmp[j];
        radix = radix * 10;
    }
    delete[]tmp;
    delete[]count;
}
//shell排序,改进的插入排序
int shellsort(int *number)
{
	for(int group=N/2;group>0;group/=2)
	{
		for(int i=group;i<N;i++)//每一个都循环,所以下面每次只交换一次
		{
			for(int j=i-group;j>=0&&(number[j]>number[j+group]);j-=group)//每次只能交换一次,交换多了就不对了
			{
				SWAP(number[j],number[j+group]);
			}
		}
	}
	return 0;
}
//插入排序
int insort(int *number)
{
	/*int temp;
	for(int i=N-2;i>=0;i--)//从大到小循环进行排序
	{
	temp=number[i];
	int j=i+1;
	while(temp>number[j])
	{
	number[j-1]=number[j];
	j++;
	if(j==N)
	break;
	}
	number[j-1]=temp;
	}*/
	int temp,j;
	for(int i=1;i<N;i++)//从小到大循环进行排序
	{
		temp=number[i];
		for(j=i;j>0;j--)
		{
			if(number[j-1]>temp)
			{
				number[j]=number[j-1];
			}
			else
			{
				break;
			}
		}
		number[j]=temp;
	}
	return 0;
}
//heap算法,堆排序,改进的选择排序
int heapsort(int *number)
{
	//建立排序堆积树
	int heap[N+1]={-1111},child,parent;
	for(int i=1;i<=N;i++)
	{
		heap[i]=number[i-1];
		child=i;
		parent=i/2;
		while(heap[child]<heap[parent]&&child>=2)//子树比根小并且有子树
		{
			SWAP(heap[child],heap[parent]);
			child=parent;
			parent=child/2;
		}
	}
	//堆排序
	int n=N;
	while(n>1)
	{
		number[N-n]=heap[1];
		SWAP(heap[1],heap[n]);
		n--;
		parent=1;
		child=2*parent;
		while(child<=n)
		{
			if(child<n&&heap[child]>heap[child+1])//有两个子树并右子树较小或
				child++;
			if(heap[parent]<=heap[child])//根比子树小
				break;
			SWAP(heap[parent],heap[child]);
			parent=child;
			child=2*parent;
		}
	}
	number[N-1]=heap[1];
	return 0;
}
//选择排序
int selsort(int *number)
{
	int temp;
	for(int i=0;i<N;i++)
	{
		int min=9999;
		for(int j=i;j<N;j++)
		{
			if(min>number[j])
			{
				min=number[j];
				temp=j;
			}
		}
		number[temp]=number[i];
		number[i]=min;
	}
	return 0;
}
//shaker排序,改进的冒泡排序
int shakersort(int *number)
{
	int left=0,right=N-1,i;
	int shift=left;
	while(left<right)
	{
		for(i=left;i<right;i++)
		{
			if(number[i]>number[i+1])
			{
				SWAP(number[i],number[i+1]);
				shift=i;
			}
		}
		right=shift;
		for(i=right;i>left;i--)
		{
			if(number[i]<number[i-1])
			{
				/*temp=number[i];
				number[i]=number[i-1];
				number[i-1]=temp;*/
				SWAP(number[i],number[i-1]);
				shift=i;
			}
		}
		left=shift;
	}
	return 0;
}
//冒泡排序
int bubsort(int *number)
{
	//int temp;
	for(int i=0;i<N-1;i++)
	{
		for(int j=0;j<N-i-1;j++)
		{
			if(number[j]>number[j+1])
			{
				SWAP(number[j],number[j+1]);
			}
		}
	}
	return 0;
}
//快速排序1(最左为轴)
void quicksort1(int *number,int left,int right)
{
	int s,i,j;
	if(left<right)
	{
		s=number[left],i=left,j=right+1;
		while(1)
		{
			while(i+1<right+1&&number[++i]<s)   ;
			while(j-1>left-1&&number[--j]>s)  ;
			if(i>=j)
				break;
			SWAP(number[i],number[j]);
		}
		number[left]=number[j];
		number[j]=s;
		quicksort1(number,left,j-1);
		quicksort1(number,j+1,right);
	}
}
//快速排序2(中间为轴)
void quicksort2(int *number,int left,int right)
{
	int i,j,s;
	if(left<right)
	{
		s=number[(left+right)/2],j=right+1,i=left-1;
		while(1)
		{
			while(number[++i]<s)  ;
			while(number[--j]>s)  ;
			if(i>=j)
				break;
			SWAP(number[i],number[j]);
		}
		quicksort2(number,left,i-1);
		quicksort2(number,j+1,right);
	}
}
//算法导论书
void quicksort3(int *number,int left,int right)
{
	int i,j,s,q;
	if(left<right)
	{
		s=number[right];
		i=left-1;
		for(j=left;j<right;j++)
		{
			if(number[j]<=s)//当两个数一样的时候交换后为0
			{
				i++;
				if(number[i]!=number[j])
				//cout<<number[i]<<‘ ‘<<number[j]<<endl;
				SWAP(number[i],number[j]);
				//cout<<number[i]<<‘ ‘<<number[j]<<endl;
			}
		}
		if(number[i+1]!=number[right])
		SWAP(number[i+1],number[right]);
		q=i+1;
		quicksort3(number,left,q-1);
		quicksort3(number,q+1,right);
	}
}
//归并排序
int mergeSort(int *data, int p, int r)  
{  
	int q;  
	int n1, n2, i, j, k; 
	if(p < r) //只有一个或无记录时不须排序   
	{  
		q = (int)((p+r)/2);      //将data数组分成两半     
		mergeSort(data, p, q);   //递归拆分左数组  
		mergeSort(data, q+1, r); //递归拆分右数组   

		 //*************************合并数组
		int *left=NULL, *right=NULL;  

		n1 = q-p+1;   
		n2 = r-q;  

		left = (int *)malloc(sizeof(int)*(n1));   
		right = (int *)malloc(sizeof(int)*(n2));  
		//检查是否分配成功
		if(left==NULL||right==NULL){
			cout<<"归并排序分配内存错误!!!"<<endl;
			return 0;
		}
		for(i=0; i<n1; i++)  //对左数组赋值  
			left[i] = data[p+i];  
		for(j=0; j<n2; j++)  //对右数组赋值  
			right[j] = data[q+1+j];  

		i = j = 0;   
		k = p;  
		while(i<n1 && j<n2) //将数组元素值两两比较,并合并到data数组  
		{  
			if(left[i] <= right[j])  
				data[k++] = left[i++];  
			else  
				data[k++] = right[j++];  
		}  

		for(; i<n1; i++) //如果左数组有元素剩余,则将剩余元素合并到data数组  
			data[k++] = left[i];  
		for(; j<n2; j++) //如果右数组有元素剩余,则将剩余元素合并到data数组  
			data[k++] = right[j];  
		free(left); 
		free(right); 
		left=NULL;
		right=NULL;
		//当不需要再使用申请的内存时,记得释放;
		//释放后应该把指向这块内存的指针指向NULL,防止程序后面不小心使用了它。 
	}
	return 0;
}      
int selectag()
{
	cout<<"输入0为退出,"<<endl
		<<"输入1为冒泡排序,"<<endl
		<<"输入2为选择排序,"<<endl
		<<"输入3为插入排序,"<<endl
		<<"输入4为希尔排序(改进的插入排序),"<<endl
		<<"输入5为Shaker排序(改进的冒泡排序),"<<endl
		<<"输入6为heap(堆)排序(改进的选择排序),"<<endl
		<<"输入7为快速排序1(最左为轴),"<<endl
		<<"输入8为快速排序2(中间为轴),"<<endl
		<<"输入9为快速排序3(算法导论),"<<endl
		<<"输入10为归并排序,"<<endl
		<<"输入11为基数排序,"<<endl
		<<"请选择排序算法:";
	return 0;
}
int creatlist(int *number)
{
	int j,temp;
	for(int i=0;i<N;i++)//随机生成1到N的数组
	{
		j=rand()%N;
		temp=number[i];
		number[i]=number[j];
		number[j]=temp;
	}
	cout<<"排序前:"<<endl;
	for(int i=0;i<N;i++)
	{
		cout<<number[i];
		if(i<N-1)
			cout<<"->";
	}
	cout<<endl;
	return 0;
}
int main()
{
	clock_t start, finish;//开始结束时间 
	double duration; //耗时
	int number[N];
	for(int i=0;i<N;i++)
		number[i]=i;
	srand((unsigned)time(NULL));
	selectag();
	int in=1,sortstatus=1;//sortstatus为是否进行了排序
	char end;//是否退出循环
	int inright=1;//输入正确
	while(in!=0)
	{
		sortstatus=1;
		while(inright)
		{
			cin.clear();//重置错误输入
			cin.sync();//清空缓冲区  不然会出现无限循环
			cin>>in;
			if(!cin.fail())//如果输入不匹配,fail()会返回真
			{
				inright=0;
			}
			else
			{
				cout<<"**********************输入有误,不是int类型,请输入int数字:";
				selectag();
			}
		}
		start = clock(); //开始计时
		switch(in)
		{
		case 0:
			cout<<"**********************确认退出???(y/n)**********************"<<endl;
			cin.clear();
			cin>>end;
			switch(end)
			{
			case ‘y‘:case ‘Y‘:
				//这里退出,所以不用selectag();
				break;
			case ‘n‘:case ‘N‘:
				selectag();
				inright=1;//重新进行输入检测
				sortstatus=0;//这次没有进行排序
				in=9999;
				break;
			}
			break;
		case 1:
			creatlist(number);
			bubsort(number);
			cout<<"冒泡排序:"<<endl;
			break;
		case 2:
			creatlist(number);
			selsort(number);
			cout<<"选择排序:"<<endl;
			break;
		case 3:
			creatlist(number);
			insort(number);
			cout<<"插入排序:"<<endl;
			break;
		case 4:
			creatlist(number);
			shellsort(number);
			cout<<"希尔排序(改进的插入排序):"<<endl;
			break;
		case 5:
			creatlist(number);
			shakersort(number);
			cout<<"Shaker排序(改进的冒泡排序):"<<endl;
			break;
		case 6:
			creatlist(number);
			heapsort(number);
			cout<<"heap(堆)排序(改进的选择排序):"<<endl;
			break;
		case 7:
			creatlist(number);
			quicksort1(number,0,N-1);
			cout<<"快速排序1(最左为轴):"<<endl;
			break;
		case 8:
			creatlist(number);
			quicksort2(number,0,N-1);
			cout<<"快速排序2(中间为轴):"<<endl;
			break;
		case 9:
			creatlist(number);
			quicksort3(number,0,N-1);
			cout<<"快速排序3(算法导论):"<<endl;
			break;
		case 10:
			creatlist(number);
			mergeSort(number,0,N-1);
			cout<<"归并排序:"<<endl;
			break;
		case 11:
			creatlist(number);
			radixsort(number,N);
			cout<<"基数排序:"<<endl;
			break;
		default:
			sortstatus=0;
			inright=1;
			cout<<"**********************输入有误,请输入正确的数字!!!**********************"<<endl;
			selectag();
			break;
		}
		finish = clock(); //结束计时
		duration=(double)(finish-start)/CLOCKS_PER_SEC;
		cout<<"本算法总耗时"<<duration<<endl;
		if(in!=0&&sortstatus)
		{
			for(int i=0;i<N;i++)
			{
				cout<<number[i];
				if(i<N-1)
					cout<<"->";
			}
			cout<<endl;
			selectag();
			inright=1;
		}
	}
	system("pause");
	return 0;
}

  

以上是关于各种排序算法练习的主要内容,如果未能解决你的问题,请参考以下文章

从搜索文档中查找最小片段的算法?

算法练习--归并排序排列题

算法练习--快速排序堆排序

算法--三色排序练习题

普通链表的各种排序及常用操作

代码练习(二维数组的定义,字符串加减,子元素的创建及绑定,排序算法)