前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >快速排序算法

快速排序算法

作者头像
爱撒谎的男孩
发布2018-05-25 16:27:08
6190
发布2018-05-25 16:27:08
举报
文章被收录于专栏:码猿技术专栏码猿技术专栏

快速排序算法

思想(从小到大排序)

  • 快速排序是使用分治法来完成的
  • 基本思想就是先从其中选取一个基准值,然后从数组的两端开始移动查找,在右边移动查找到比基准值小的数据停止移动,此时在左边查找到比基准值大的数据也停止查找,交换这两个查找到的数据,交换完成之后两端继续移动查找,如果左边找到比基准值大的,右边找到比基准值小的数据,再次交换。直到查找到同一个数据上(相遇)或者”擦肩而过”。那么将基准值相遇的那个值交换,此时就能够保证在基准值左边的都是比基准值小的,在其右边的都是比其大的数,此时一轮查找结束。接下来这个基准值将一个数组分成了两半,左边的是小的,右边是大的,那么我们再分别对左边和右边的数据进行相同的操作,直至不可拆分成新的子序列为止。
  • 快速排序的最坏运行时间是O(n2),但期望的运行时间是O(nlgn)
  • 测试

123456

int[] array={ 9,7,4,67,45,2,24,33,22,45,88,12,1,0,25};quickSort(array, 0, array.length-1);for (int i = 0; i < array.length; i++) { System.out.print(array[i]+"\t");}

另外一种方式

选取数组的第一个数为基准值

  • 我们选取数组的第一个元素作为基准值
  • 此时先从数组的最右边开始查找,如果找到比基准值小的停止查找,再从最左边开始查找,直至找到比基准值大的,那么两边就交换,交换完成之后,最右边再次开始查找,找到就等待左边找到数交换,直至双方相遇。那么把相遇的那个点的数据和基准值交换即可,那么现在在基准值左边的都是小的,在右边的都是大的,此时的基准值将数组分成了两个子序列,再对子序列进行重复的操作,直到不可拆分成子序列。
  • 实现的代码
代码语言:javascript
复制
public static void quickSort(int[] arr,int low,int high){
	        
	        //递归结束的条件,如果此时的子序列只有一个元素就是low=high,就不用排序了
	        if(low>=high){
	            return;
	        }
	        
	        int i=low;   //i从最左边开始查找
	        int j=high;   //i从最右边开始查找
	        int temp = arr[low]; //设置基准值为第一个元素,temp
	        
	        //如果此时的i和j没有相遇,一直进行下去
	        while (i<j) {
	        	//先从右边开始查找,如果没有找到比基准值小的并且没有相遇,那么继续向右查找
	            while (temp<=arr[j]&&i<j) {
	                j--;   //向左移动
	            }
	            
	            //再从左边开始查找,如果没有找到比基准值大的并且没有相遇,那么继续向左查找
	            while (temp>=arr[i]&&i<j) {
	                i++;   // 向右移动
	            }
	           
	           //代码能够运行到这里,那么表示已经找到了右面小于基准值的,左面大于基准值的,那么就可以交换数据了
	           //这里的i<j用于控制在最后相遇的时候还要交换数据,不必交换了,可以省去一次的交换
	          if (i<j) {
	        	  	//交换数据
	        	   	int t = arr[j];
	                arr[j] = arr[i];
	                arr[i] = t;
	          }
	             

	        }
	        
	        //最后将基准为与i和j相等位置的数字交换
	         arr[low] = arr[i];  //第一个元素设置为i和j相遇的那个值
	         arr[i] = temp;   //相遇的那个地方设置为基准值
	         
	        //递归调用左半数组,以基准值为中心切割
	        quickSort(arr, low, j-1);
	        //递归调用右半数组
	        quickSort(arr, j+1, high);
	    }
  • 测试
代码语言:javascript
复制
int[] array={ 9,7,4,67,45,2,24,33,22,45,88,12,1,0,25};
quickSort(array, 0, array.length-1);

for (int i = 0; i < array.length; i++) {
	System.out.print(array[i]+"\t");
}

另外一种方式

代码语言:javascript
复制
public static int partition(int[] array,int low,int high){
		  int i=low;
		  int j=high;
		  int temp=array[low];  //选取第一个为基准数
		  //如果此时的还没有相遇,表示没有结束
		  while(i<j){
			  //因为基准数是最左面的,因此从最右面开始查找
			  //当当前的值比基准值大,并且i和j不相等,即是没有相遇
			  while(temp<array[j]&&i<j){
				  j--;   //向左移动,继续查找
			  }
			  
			  //从左面开始查找,如果查找到的数据array[i]小于基准值并且i和j没有相遇,那么继续向右移动查找
			  while(array[i]<temp&&i<j){
				  i++;  //继续向右移动查找
			  }
			  
			//代码能够运行到这里,那么表示已经找到了右面小于基准值的,左面大于基准值的,那么就可以交换数据了
	          if (i<j) {
	        	   	int t = array[j];
	                array[j] = array[i];
	                array[i] = t;
	          }
		  }
		  
		  low=i;
		  high=j;
		  
		  return j ;   //返回当前的基准值在数组中的索引,用于分割子序列
	 }

	 
	 public static void quickSort1(int[] arrary,int low,int high){
		 //停止条件,如果low>high表示相遇,那么停止递归
		 if(low>high){
			 return;
		 }
		 int index=partition(arrary, low, high);  //获取基准值的位置
		 quickSort1(arrary, low, index-1);   //左边的
		 quickSort1(arrary,index+1,high);  //右边的
		 
	 }

为什么从最右边开始查找

  • 如果从最左边开始查找,那么有可能某一次查找到了比基准值大的数,停止查找,等待最右边查找到比基准值小的数,但是此时最右边一直在查找,直到和其相遇都没有查找到比基准值小的数据,那么此时的的基准值就需要和这个比它还大的值交换,那么出现的结果就是此时的数组的第一个数是比基准值大的,违背了左边都是比基准值小的,右边都是比基准值大的。
  • 如果从最右边开始查找,即使当某一个时刻查找到了比基准值小的数据,停止查找,等待左边查找到比基准值大的数据。但是左边没有找到,直至相遇,那么此时相遇的这个数任然是比基准值小的,因此和基准值交换是没有问题的
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-05-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 快速排序算法
    • 思想(从小到大排序)
      • 另外一种方式
    • 选取数组的第一个数为基准值
      • 另外一种方式
      • 为什么从最右边开始查找
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档