分治法--快速排序

原始版本:
package com.duoduo.test1;
/*
 * 快速排序:基于分治策略
 * 算法思想:1 分解(取基准元素,将其左右两侧划分
 * 2 治理:对两个子序列进行快速排序
 * 3 合并: 将排好序的两个子序列合并在一起,得到原问题的解
 * 执行过程:取基准元素  从右向左扫描 找<基准元素的值  进行交换i++  
 *         从左向右扫描 找到>基准元素的值 交换值并j--     不断重复步骤  直到i ,j 指针重合 
 *         返回该位置mid=i 恰好是基准元素的位置
 *         之后分别对左右两侧的子序列进行排序  合并结果
 * 
 * */
import java.util.Scanner;
public class QuickSort {
	public static void main(String [] args) {
		Scanner sc=new Scanner(System.in);   //系统键盘录入数据
		System.out.println("请先输入要排序的数据的个数:");
		int N=sc.nextInt();
		System.out.println("请输入要排序的数据 :");
		int [] arr=new int[N];
		for(int i=0;i<N;i++) {
			arr[i]=sc.nextInt();
		}
		
		quickSort(arr,0,N-1);              //快速排序
		System.out.println("排序后的序列为:");
		for(int i=0;i<N;i++)
			System.out.print(arr[i]+" ");
	}
	
	/*快速排序递归算法*/
	public static void quickSort(int [] arr,int low,int high) {
		int mid;
		if(low<high) {
			mid=partition(arr,low,high);      //基准位置
			quickSort(arr,low,mid-1);         //左子序列
			quickSort(arr,mid+1,high);        //右子序列
		}
	}
		
	/*划分序列,找到基准元素位置*/
	public static int partition(int [] arr,int low,int high) {
		int i=low;
		int j=high;
		int temp=arr[low];
		
		while(i<j) {
			while(i<j&&arr[j]> temp)    //从右往左扫描  找到比基准元素小的值为止  跳出循环
				j--;
			if(i<j) { 
				int tmp=arr[i];     //交换元素位置
                                arr[i]=arr[j];
                                arr[j]=tmp;
                                i++;
			}                            //交换二者的值 并i++ 右移
			while(i<j&&arr[i] <=temp)   //从左往右扫描   找到比基准元素大的值为止
				i++;
			if(i<j) {
				int tmp=arr[i];     //交换位置
				arr[i]=arr[j];
				arr[j]=tmp;
                                j--;               //交换二者的值   并j--
		       }
		}
		return i;                        //返回最终划分完成后基准元素所在的位置            
	}

}


结果:


优化版本:

原始版本每次都是和基准元素进行交换,没必要。游湖版本交换元素的个数减少~

/*划分序列,找到基准元素位置*/
		public static int partition(int [] arr,int low,int high) {
			int i=low;
			int j=high;
			int temp=arr[low];
			
			while(i<j) {
				while(i<j&&arr[j]>temp) j--;    //向左扫描
				while(i<j&&arr[i]<=temp) i++;   //向右扫描
				if(i<j) {                       //找到在右边比基准元素小的 和在左边比基准大的两个值
					int tmp;                //r[i]和r[j]交换  i++ j--
					tmp=arr[i];
					arr[i]=arr[j];
					arr[j]=tmp;
					i++;
					j--;
				}
			}   
                        if(arr[i]>temp) {                        //i=j 停止  判断arr[i]和基准元素
				int tmp;                         //若arr[i]> temp  则arr[i-1] 和arr[low] 交换
				tmp=arr[i-1];  
				arr[i-1]=arr[low];
				arr[low]=tmp;
				return i-1;                      //返回位置i-1
			}
			int tmp;                                 //若arr[i]<=temp
			tmp=arr[i];                              //arr[i] 和 arr[low]交换
			arr[i]=arr[low];
			arr[low]=tmp;
			return i;	                         //返回位置i
	}

结果:




最终版本(“填坑”)

package com.duoduo.day316;
import java.util.Scanner;
public class QuickSort {
	public static void main(String [] args) {
		Scanner sc=new Scanner(System.in);   //系统键盘录入数据
		System.out.println("请先输入要排序的数据的个数:");
		int N=sc.nextInt();
		System.out.println("请输入要排序的数据 :");
		int [] arr=new int[N];
		for(int i=0;i<N;i++) {
			arr[i]=sc.nextInt();
		}
		
		quickSort(arr,0,N-1);              //快速排序
		System.out.println("排序后的序列为:");
		for(int i=0;i<N;i++)
			System.out.print(arr[i]+" ");
	}
	
	/*快速排序递归算法*/
	public static void quickSort(int [] arr,int low,int high) {
		int mid;
		if(low<high) {
			mid=partition(arr,low,high);      //基准位置
			quickSort(arr,low,mid-1);         //左子序列
			quickSort(arr,mid+1,high);        //右子序列
		}
	}
		
	/*划分序列,找到基准元素位置*/
	public static int partition(int [] arr,int low,int high) {
		int i=low;
		int j=high;
		int temp=arr[low];
		
		while(i<j) {
			while(i<j&&arr[j]> temp)    //从右往左扫描  找到比基准元素小的值为止  跳出循环
				j--;
			if(i<j) { 
				arr[i++]=arr[j];         //交换二者的值 并i++ 右移
			}                            
			while(i<j&&arr[i] <=temp)   //从左往右扫描   找到比基准元素大的值为止
				i++;
			if(i<j) {
				arr[j--]=arr[i];              //交换二者的值   并j--
		       }
		}
		arr[i]=temp;                       //填充基准元素
		return i;                        //返回最终划分完成后基准元素所在的位置            
	}

}


分析时间复杂度:

best 最好时间复杂度:

分解:  划分函数partition ()   扫描元素O(n)

解决子问题:每次都能分解为规模n/2的子问题    2T(n/2)

合并:  原地排序  无需操作 已经有序

T(n)=2T(n/2)+O(n)=O(nlogn)

空间复杂度: 辅助变量O(1)   递归调用O(logn)


worst最坏时间复杂度:

分解:O(n)

解决子问题 :T(n-1)  基准元素左(右侧)没有元素   单侧递归树

总:T(n)=T(n-1)+O(n)=O(1)+O(2)+....O(n)= O(n(n+1)/2) -----O(n的平方)

空间递归 O(n)



平均时间/空间复杂度:

k-1    基准元素位置K    n-k


O(nlogn)--------------------------------O(logn)


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值