Java算法总结(6)交换排序

1、交换排序

在这里插入图片描述
  上篇介绍了选择排序,那么接下来给大家介绍比较排序中的交换排序,“交换”顾名思义就是两两比较后,当满足某种条件时,互换位置;该排序包括冒泡排序和快速排序。

2、冒泡排序

  冒泡排序是一种相对简单的比较排序方法,通过相邻元素两两比较,当满足某种比较条件时,交换彼此位置,它的整个运行过程类似水中气泡从下往上,逐渐变大的过程,所以叫冒泡排序。

2.1 算法分析

1、 算法时间复杂度:O(N*2);
2、 算法空间复杂度:O(1);
3、 稳定排序;

2.2 算法步骤

1、 从无序列表中比较2邻元素。如果第一个比第二个大,就交换它们两个;
2、 对每一对相邻元素做同样的工作,直到最后一个元素为最大的数为止,并使得无序列表的长度length=length-1;
3、 持续每次对越来越少的元素重复上面的步骤,直到无序列表的长度length=1为止;

2.3 冒泡排序Java代码
/**
	 * 冒泡排序
	 * 算法复杂度O(N*2)
	 * @param a
	 */
	public static <T extends Comparable<? super T>> void bubbleSort(T[] a) {
		//外层比较次数
		for (int i = 0; i < a.length-1; i++) {
			//两两交换位置
			for (int j = 0; j < a.length-i-1; j++) {
				if(a[j].compareTo(a[j+1])>0) {
					swap(a,j,j+1);
				}
			}
		}
	}

3、快速排序

  基于分治策略,以某种规则方式从序列中找到一个基准点(普遍以序列第一个元素为基准),将序列划分为两个子序列,其中基准点左边的子序列所有元素都小于等于基准点,基准点右边的子序列所有元素都大于基准点,然后对子序列继续递归调用以上思想,直到子序列的大小为零或一,也就是已经排序好了;

3.1 算法分析

1、 时间复杂度:最坏时间O(N*2),最好时间O(NlogN);平均时间O(NlogN);
2、 空间复杂度:O(logN),虽然还是使用原来的序列,但是递归需要消耗栈空间;
3、 不稳定排序;

3.2 算法步骤

1、 找出基准点pivot,包括以下三种方式:

  • 以序列的第一个元素作为基准点(本实例采用的策略),对于预排的情况比较糟糕;
  • 随机生成序列中的位置,作为基准点;
  • 三数中值法(第一个元素,中间元素,最后一个元素取中间值作为基准点),是相对较好的基准点选择法;

2、 基于基准点,将序列划分为两个子序列,其中基准点左边的序列所有元素都小于等于基准点,而基准点右边的子序列所有元素都大于基准点;
3、 对子序列迭代调用以上步骤,直到序列元素为0或1为止;

3.3 图解

在这里插入图片描述

3.4 快速排序Java代码
/**
	 * 柯里化调用快速排序法, 
	 * @param arr 需要排序的原始数组
	 * @return 
	 */
	public  static  <T extends Comparable<? super T>> void quickSort(T[] arr) {		
		//调用快速排序法	
		quickSort(arr,0,arr.length-1);
	}
	/**
	 * 快速排序法,
	 * 算法的运行时间为O(n^2);
	 * @param arr 需要排序的原始数组
	 * @return 
	 */
	private static  <T extends Comparable<? super T>> void quickSort(T[] arr,int low,int high) {		
		if(low<high) {
			//1、基于基准点,将序列分为左右两个子序列
			int middle=getMiddle(arr,low,high);
			//2、递归调用
			//左侧
			quickSort(arr,low,middle-1);
			//右侧
			quickSort(arr,middle+1,high);
		}
	}
	
	/**
	 * 获取对分位置;
	 * 使得数组的对分位置左边永远小于等于对分位置,右边永远大于对分位置
	 * @param list
	 * @param low
	 * @param high
	 * @return
	 */
	private static  <T extends Comparable<? super T>> int getMiddle(T[] arr,int low,int high) {
		//1、基准点
		T temp=arr[low];
		//2、将序列分为两个子序列,其中基准点左边的子序列所有元素都小于等于基准点值,而基准点右边的子序列恰相反;
		while(low<high) {
			//2.1 从右往左遍历直到遇到小于等于基准点的位置;
			while(low<high && arr[high].compareTo(temp)>=0) {
				high--;
			}
			
			arr[low]=arr[high];
			//2.2从左往右遍历直到遇到大于基准点的位置;
			while(low<high&& arr[low].compareTo(temp)<0) {
				low++;
			}
			arr[high]=arr[low];
			
		}
		
		arr[low]=temp;
		//3、返回基准点位置
		return low;
	}
4、简单测试
package xw.zx.algorithm.sort;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class SortTest {
	private static final int ARRAY_LEN=40;
	private static Integer[] arr=new Integer[ARRAY_LEN];
	public static void main(String[] args) {
		List<Integer> l=new ArrayList<>();
		for (int i = 0; i < ARRAY_LEN; i++) {
			l.add(i+1);			
		}
		//乱序列表
		Collections.shuffle(l);
		//列表转换成数组
		arr=l.toArray(new Integer[0]);
		System.out.println("输出原数组");
		printVal(arr);
		//冒泡、快速排序
		//AllSorts.bubbleSort(arr);
		AllSorts.quickSort(arr);
		System.out.println("输出排序后的数组");
		printVal(arr);
	}
	/**
	 * 打印数组
	 * @param arr
	 */
	private static void printVal(Integer[] arr) {
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i]+" ");
			
		}
		System.out.println("");
	}
}

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值