【算法】常用排序算法复习

一、快速排序

快速排序的思想就是分治法。分就是将序列分成几个部分,治就是对每一部分进行治理、排序

基本的思路是,首先是选择一个基准数,然后进行一次排序,排序规则是:遍历一次,基准数正确归位即比基准数小的都在它的左边,比它大的都在它的右边。

然后再对基准数左边的数重复排序规则,右边的数也是同样的规则,如此地递归调用,直到最小的部分只有一个数。那这样所有的大分区、小分区就都是有序的了。

对于基准数的选择,一般是选取要排序的那一部分的第一个数,也有的做法是选择中间的数。道理一样。


借用http://blog.csdn.net/morewindows/article/details/6684558 的例子解释这个过程

------我是分割线-----

以一个数组作为示例,取区间第一个数为基准数。

0

1

2

3

4

5

6

7

8

9

72

6

57

88

60

42

83

73

48

85

初始时,i = 0;  j = 9;   X = a[i] = 72

由于已经将a[0]中的数保存到X中,可以理解成在数组a[0]上挖了个坑,可以将其它数据填充到这来。

从j开始向前找一个比X小或等于X的数。当j=8,符合条件,将a[8]挖出再填到上一个坑a[0]中。a[0]=a[8]; i++;  这样一个坑a[0]就被搞定了,但又形成了一个新坑a[8],这怎么办了?简单,再找数字来填a[8]这个坑。这次从i开始向后找一个大于X的数,当i=3,符合条件,将a[3]挖出再填到上一个坑中a[8]=a[3]; j--;

 

数组变为:

0

1

2

3

4

5

6

7

8

9

48

6

57

88

60

42

83

73

88

85

 i = 3;   j = 7;   X=72

再重复上面的步骤,先从后向前找,再从前向后找

从j开始向前找,当j=5,符合条件,将a[5]挖出填到上一个坑中,a[3] = a[5]; i++;

从i开始向后找,当i=5时,由于i==j退出。

此时,i = j = 5,而a[5]刚好又是上次挖的坑,因此将X填入a[5]。

 

数组变为:

0

1

2

3

4

5

6

7

8

9

48

6

57

42

60

72

83

73

88

85

可以看出a[5]前面的数字都小于它,a[5]后面的数字都大于它。因此再对a[0…4]和a[6…9]这二个子区间重复上述步骤就可以了。

------我是分割线-----

Java代码如下:

public static void quickSort(int[] data,int start,int end){
		int i = start;
		int j = end;
		int key = data[i];
		while(i<j){
			while(data[j]>key && j>i){//移动下标,找到比key小的数
				j--;
			}
			data[i] = data[j];//将比key小的数放到左边
			while(data[i]<key && j>i){//移动下标,找到比key大的数
				i++;
			}
			data[j] = data[i];//将比key大的放到右边
		}
		data[i] = key; //归位,将基准数key放在正确的位置
		if(i-1>start){
			quickSort(data, start, i-1);//对左边的数进行排序
		}
		if(i+1<end){
			quickSort(data, i+1, end);//对右边的数进行排序
		}
	}

时间复杂度:最好O(nlogn),最坏O(n^2) 。具体我也不是很清楚怎么推导,涉及到主定理。算法导论里有推导过程


二、选择排序

设数组为a[0…n-1]。

1.      初始时,数组全为无序区为a[0..n-1]。令i=0

2.      在无序区a[i…n-1]中选取一个最小的元素,将其与a[i]交换。交换之后a[0…i]就形成了一个有序区。

3.      i++并重复第二步直到i==n-1。排序完成。

public static void selectionSort(int[] a){
		int i,j,minIndex;
		for(i=0;i<a.length;i++){
			minIndex = i;
			//每一趟记录最小数的index,也就是每一趟将最小的数放到前面
			for(j=i+1;j<a.length;j++){
				if(a[j] < a[minIndex])
					minIndex = j;
			}
			int temp = a[i];
			a[i] = a[minIndex];
			a[minIndex] = temp;
		}
		
	}



三、插入排序

设数组为a[0…n-1]。

1.      初始时,a[0]自成1个有序区,无序区为a[1..n-1]。令i=1

2.      将a[i]并入当前的有序区a[0…i-1]中形成a[0…i]的有序区间。

3.      i++并重复第二步直到i==n-1。排序完成。


public static void insertSort(int[] a){
		int i,j;
		for(i = 1;i<a.length;i++){
			int temp = a[i];
			for(j=i;j>0 && temp<a[j-1];j--){
				a[j] = a[j-1];
			}
			a[j] = temp;
		}
	}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值