分治法--快速排序

原始版本:
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]。 #### 算法的具体步骤 具体来说,在每次划分过程中选取一个基准值(pivot),通常可以选择序列的第一个或者最后一个元素作为基准值。接着调整序列中其他元素的位置,使所有小于等于基准值的元素移动到它的左侧,而所有大于基准值的元素则被放置在其右侧[^4]。 ```python def partition(arr, low, high): pivot = arr[low] i = low + 1 j = high while True: while i <= j and arr[i] <= pivot: i += 1 while i <= j and arr[j] >= pivot: j -= 1 if i > j: break arr[i], arr[j] = arr[j], arr[i] arr[low], arr[j] = arr[j], arr[low] return j ``` 当完成上述过程之后,就得到了一个新的索引`mid`,它指向的就是当前选定的基准值所在的新位置;此时可以认为已经完成了针对这个特定基准的一次有效划分。 #### 对子序列递归处理 接下来就是对左右两侧形成的新的子序列再次执行相同的操作——即选择新基准并重新排列剩余项直至不能再进一步细分为止。最终得到的结果就是一个完全有序化的列表[^5]。 ```python def quicksort(arr, low, high): if low < high: mid = partition(arr, low, high) quicksort(arr, low, mid - 1) quicksort(arr, mid + 1, high) ``` 值得注意的是,对于非常短的小规模输入集(比如长度不超过20的情况),采用更简单的插入排序可能会更加高效[^2]。因此实际编程实践中有时会在递归调用到达一定深度时切换至更为适合小样本量的方法来优化性能表现。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值