各种排序算法总结。

今天来总结一下排序算法。

1.冒泡排序:

就是从第一个开始依次与后面的值比较,重复上n-1轮就能得到排好序的数组了。

//冒泡排序.时间复杂度为O(n^2).空间复杂度为O(1).
void Bsort(int a[],int n)
{
	int i,j;
	if(n<=1)            //若数组长度小于等于1则直接退出。
	{
		return;
	}
	for(i=0;i<n-1;i++)             //需要这么多次的寻找最小值。
	{
		for(j=0;j<n-i-1;j++)         //每次寻找需要比较的次数。
		{
			if(a[j]>a[j+1])          //若后者大于前者进行交换。
			{
				swap(&(a[j]),&(a[j+1]));
			}
		}
	}
	return;
}

2.选择排序:

先找第一个数为擂主,后面的数依次与它比较交换,重复操作即可。

//选择排序。时间复杂度为O(n^2).空间复杂度为O(1).
void Select(int a[],int n)
{
	int i,j;
	if(n<=1)                   //若数组长度小于等于1则直接退出。
	{
		return;
	}
	for(i=0;i<n-1;i++)         //循环擂台主。
	{
		for(j=i+1;j<n;j++)     //每个擂台主需要进行守擂的次数。
		{
			if(a[j]<a[i])         //若大于擂主,与擂主交换。
			{
				swap(&(a[j]),&(a[i]));
			}
		}
	}

	return;
}

3.插入排序:

//插入排序.时间复杂度为O(n^2).空间复杂度为O(1).
void Insert(int a[],int n)
{
	int i,j;
	int b;
	if(n<=1)             //若数组长度小于等于1则直接退出。
	{
		return;
	}
	for(i=1;i<n;i++)     //需要插入的值的个数。   
	{
		b=a[i];
		for(j=i;j>0;j--)       //每次插入寻找插入位置。       
		{
			if(a[j-1]>b)       
			{
				a[j]=a[j-1];    //插入数据。
			}
			else{
				break;          
			}
		}
		a[j]=b;               
	}
	return;
}

4.希尔排序:

它就是优化版的插入排序。

//希尔排序.时间复杂度为O(n^1.3),空间复杂度为O(1).

void Shell(int a[],int n)
{
	int i,j;
	int x,y;
	if(n<=1)                  //若长度小于等于1就退出。
	{
		return;
	}
	for(i=n/2;i>=1;i/=2)         
	{
		for(j=i;j<n;j++)
		{
			x=a[j];
			for(y=j;y>=i;y-=i)
			{
				if(a[y-i]>x)
				{
					a[y]=a[y-i];
				}
				else{
					break;
				}
			}
			a[y]=x;
		}
	}
	return;

}

5.堆排序:

//堆排序。
//(1)向下调整法
void AdjustDown(int a[],int n,int p)
{
	int left=2*p+1;
	int right=2*p+2;
	int max;
	if(left>=n)
	{
		return;
	}
	max=left;
	if(right<n && a[right]>a[max])
	{
		max=right;
	}
	if(a[max]>a[p])
	{
		swap(a+max,a+p);
	}
	AdjustDown(a,n,max);
}
//(2)建大堆。
void MakeHeap(int a[],int n)
{
	int i=0;
	for(i=(n-2)/2;i>=0;i--)
	{
		AdjustDown(a,n,i);
	}
	return;
}

//堆排序。
void HeapSort(int a[],int n)
{
	int i=0;
	for(i=0;i<n-1;i++)        
	{
		swap(a+0,a+(n-1-i));   //将堆顶与堆尾交换,在进行建堆,循环下去就可以了。
		MakeHeap(a,n-i-1);
	}
	for(i=0;i<n;i++)
	{
		printf("%d ",a[i]);  //打印。
	}
}

6.归并排序:

采用归并的思想。将数组分为好几块,分别合并,最后在一起合并即可。

(1)递归方法:

//归并排序。
void MergeArray(int a[],int x,int y,int z,int *m)
{
	int size=x;                //下标。
	int p1=x;                  //第一个值。
	int p2=y;                  //中间的值。
	while(p1<y && p2<z)             //当满足条件时。
	{
		if(a[p1]<a[p2])          //若小于,将p1进行搬运到新的数组里。
		{
			m[size++]=a[p1++];
		}
		else{
			m[size++]=a[p2++];   //否则搬运p2.
		}
	}
	while(p1<y)                     //当p1小于中间值时
	{
		m[size++]=a[p1++];         //继续将后面所有的值放入新数组里。
	}
	while(p2<z)
	{
		m[size++]=a[p2++];           
	}
	memcpy(a+x,m+x,sizeof(int) * (z - x));  //将整个新数组赋值给原来的数组。
}
void _MergeSort(int a[],int x,int z,int *m)
{
	int mid;
	if(z-x<=1)
	{                           //若数组元素只有一个或没有,退出。
		return;
	}
	mid=x+(z-x)/2;             //求中间值。
	_MergeSort(a,x,mid,m);      //递归左半边。
	_MergeSort(a,mid,z,m);       //递归右半边。

	MergeArray(a,x,mid,z,m);

}

void MergeSort(int a[],int n)
{
	int *m=(int *)malloc(sizeof(int)*n);    //开辟空间。

	_MergeSort(a,0,n,m);     //调用归并排序。
	free(m);                //释放这个空间。
}

(2)非递归方法:

//非递归归并排序。
void MergeLoop(int a[],int n)
{
	int *m=(int *)malloc(sizeof(int)*n);   //先开辟空间。
	int i,j;
	int start,mid,end;                   //定义三个变量。
	if(n<=1)                           //若数组个数小于等于1,则直接退出。
	{
		return;
	}
	for(j=1;j<n;j=j*2){                 //每次合并数组的大小。1  2  4   8 ...
	for(i=0;i<n;i+=2*j)                 //将原数组分成多少组小数组。
	{
		start=i;                       //将三个变量赋值。
		mid=i+j;
		end=mid+j;
		if(mid>n)                    //若超过了数组大小,那就赋值1.
		{
			mid=n;
		}
		if(end>n)
		{
			end=n;
		}
		MergeArray(a,start,mid,end,m);     //调用函数合并数组。
	}
	}
	return;
}

7.快速排序。

就是确定一个中间值,将比它小的放前面,比它大的放后面,在在各个数组里继续使用这个方法即可。

//快速排序。时间复杂度:O(NlogN)空间复杂度:O(N)。
void SortArray(int a[],int left,int mid,int right)     //比较函数。
{
	int x=left;
	if(mid==right)                     //若中间值与最后的值相等,则直接退出。
	{
		return;
	}
	for(x=left;x<mid;x++)             //先比较左半边。
	{
		if(a[x]>a[mid])
		{
			swap(a+x,a+mid);
		}
	}
	for(x=mid+1;x<right;x++)          //在比较右半边。
	{
		if(a[x]<a[mid+1])
		{
			swap(a+x,a+(mid+1));
		}
	}
}
//非递归快排
void FastLoop(int a[],int n)
{
	 int left;
	 int right;
	 int mid;
	 int i,j;
	 if(n<=1)          //若数组个数小于等于1直接退出。
	 {
		 return;
	 }
	 for(i=1;i<n;i++)           
	 {
		 for(j=0;j<n;j+=2*i+1)
		 {
			 left=j;               //确定三个值。
			 mid=j+i;
			 right=mid+i;
			 if(mid>n)
			 {
				 mid=n;
			 }
			 if(right>n)           //若中间和最后的值等于数组大小,就将它赋成数组大小。
			 {
				 right=n;
			 }
			 SortArray(a,left,mid,right);    //调用这个比较函数即可。
		 }
	 }
	 return;

}

最后给大家稍微总结一下:

这就是排序的大部分算法了,这里的算法代码不是很重要,重要的是思想和方法,希望大家能下去好好想想每个排序的具体应用思想,这样才能让大家掌握的更加牢固。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值