交换类排序总结

交换类排序总结

顾名思义,交换类排序,也就是通过一系列的交换元素过程,把原本逆序的元素交换为正确的顺序的排序方法

 

一.简单的交换类排序——冒泡排序

 

通过多趟的扫描,每趟扫描过程中,将相邻的元素中较大的交换至后面,这样每一趟结束时,最大的那个元素就“沉”到最后面,通过n-1趟的交换,直到只剩下一个元素在最前面,已经不需要交换了,完成排序

 

不过,冒泡排序写代码的时候要注意优化,下面是非优化版本

简单版本的冒泡排序

void Bubble_Sort(int a[],int n)
{
	for (int i = 1; i <= n-1; i++)
	{
	
		for (int j = 0; j < n-i; j++)
		{
			if (a[j]>a[j+1])
			{
				int temp=a[j+1];
				a[j+1]=a[j];
				a[j]=temp;
			
			}
		}

	}
}

  

时间复杂度分析:这样看来,冒泡的最好时间复杂度和最坏时间复杂度都为O(n²);

最好的情况其实是可以优化的,那就是加入元素已经是排好序的话,我们可以用一个标志量来控制

void Bubble_Sort(int a[],int n)
{
	bool change=true;
	for (int i = 1; i <= n-1&&change; i++)
	{
		change=false;
		for (int j = 0; j < n-i; j++)
		{
			if (a[j]>a[j+1])
			{
				int temp=a[j+1];
				a[j+1]=a[j];
				a[j]=temp;
				change=true;
			}
		}

	}
}

  

 

这样看来,冒泡排序的最好时间复杂度为O(n)了,外层循环实际上不进行了,只执行i=1的时候,因为元素是排好序的

最坏情况:仍然为O(n²)

 

二.快速排序(QuickSort)

  我们可以回头过来看冒泡排序,通过它来理解所谓的比较排序到底是怎么一种思想,冒泡排序是通过不停地比较相邻的元素来排序,在一趟又一趟的扫描过程中完成排序,在这一过程中,比较是精髓和关键点,但是,在冒泡排序的比较过程中,我们可以发现,它每次只能比较相邻的元素,这样来看,效率是比较低的,能不能一次比较多个数来提高效率呢,快速排序的思想就是这样的,一趟比较多个元素

            快速排序的思想

     1.选取一个数作为标杆(选取第一个数),将数组中大于标杆数的元素都放到标杆数的右边,数组中小于标杆数的元素都放到标杆数的左边,记录下标杆数的位置

    2.依据标杆数的位置,对标杆数左边的子数组重复第一步,直到左边只剩下一个数字

    3.依据标杆数的位置,对标杆数左边的子数组重复第一步,直到左边只剩下一个数字

这样就完成了大名鼎鼎的快速排序,同时做到了一次排多个数字

 

    一趟快速排序的实施步骤:

      1.选取第一个数字作为标杆数,令low=其下标,令high=最后一个数字的下标,暂存变量x=a[low];

      2从high到low遍历,将小于x的数字全部移到x的左边

      3.从low到high遍历,将大于x的数字全部移到x的右边

      4.当low=high的时候,停止遍历,最后返回标杆数x的位置

    快速排序的实施步骤:

      1.求得原数组标杆数的位置

      2.利用标杆数位置,递归调用左边的子数组

      3.利用标杆数位置,递归调用右边的子数组

 

具体代码如下:

 

int Quick_Sort_Once(int a[],int low,int high)
{
	int x=a[low];
	while(low<high)
	{
		while(low<high&&a[high]>=x)
		{
			high--;
		}
		if(low<high)
		{
			
			a[low]=a[high];
			low++;
		}
		while(low<high&&a[low]<x)
		{
			low++;
		}
		if(low<high)
		{
			a[high]=a[low];
			high--;
		}	
	}
	a[low]=x;
	return low;
}
void Quick_Sort(int a[],int low,int high)
{
	if(low<high)
	{
		int x=Quick_Sort_Once(a,low,high);
		Quick_Sort(a,low,x-1);
		Quick_Sort(a,x+1,high);
	
	}
}

  

注意事项:注意Quick_Sort()函数中if(low<high)容易漏掉,这个必须有,不然,就会有无限递归调用,递归栈就会超出内存,程序崩溃

 

时间复杂度分析:

最坏的情况是:原数组本来就有序,这时候,左边子数组总是为空,右边子数组为n-1,所以总的时间复杂度为n-1+n-2+n-3+....+1=O(n²),即最坏的时间复杂度为O(n²);

最好的情况是:数组的第一个数正好是中间大的,这时候总的时间复杂度为:T(n)=O(n)+2T(n/2),根据这个式子可以推导出最好的时间复杂度为O(nlog2(n));

 

空间复杂度分析:

 

一般空间复杂度假如没有的递归的话为O(1),有递归的话那就看递归栈的深度了,递归栈的深度,那就看递归进层能有多深,这个递归明显是个二叉树式的递归,最好的情况是个满二叉树,因此树的深度就为递归栈的深度(最大只需要容纳几次push),树的深度为log2(n),所以空间复杂度为log2(n);

 

 

 

稳定性:不稳定

 

举个栗子:5644;

明显排序的时候后一个4是先填坑的,填到了5这个位置,这样一来他们的 顺序就颠倒了,所以是不稳定的,类似这样的情况时,他们都是不稳定的

 

posted @ 2016-11-24 22:18  LT.C#  阅读(891)  评论(0编辑  收藏  举报