冒泡排序和快速排序(Java实现)

本文详细介绍了两种经典的排序算法——冒泡排序和快速排序。冒泡排序通过不断交换相邻元素实现排序,时间复杂度最好情况为O(n)。快速排序采用分治策略,以基准元素划分数组,递归进行排序,平均时间复杂度为O(nlogn)。文章还给出了两种排序的具体Java实现,并分析了它们的稳定性及适用场景。
摘要由CSDN通过智能技术生成

排序算法

Java提供了7中常见的排序方法:冒泡、插入、选择、快速、希尔、归并和堆

衡量一些算法的相关属性:时间复杂度、空间复杂度、稳定性

冒泡排序

基本思路: 从第一个元素开始比较相邻的两个元素,如果第一个比第一个大或小,就互换它们的位置,这样先比较完一次,然后抛弃最大或最小的继续比较,直到排序完成。

具体实现:

{4,2,3,5,7,6,8,1,9}

i = 0 k = 1 (定义两个变量代表数组下标)

自然排序(从小到大)
最简单的方法就是嵌套循环(for循环)   利用这个想法  大致描述一下排序过程
外层循环由 i 控制(i代表数组下标)从1开始 i < arr.length  
外层循环控制的其实就是内层比较的次数  跟排序本身没有任何关系
里层循环  k 从0开始遍历 k < arr.length-i  如果arr[k] > arr[k+1]  
那么两个元素互换  然后执行k++  继续比较arr[k]和arr[k+1] 
如果arr[k] <= arr[k+1]  不互换元素  直接进行k++ 操作  
这样循环比较  直到内层第一次循环比较结束  
第一次循环结束后就可以找出数组中最大的元素   那么下次比较的时候就可以跳过这个最大的元素  
所以内层控制的范围应该是k  < arr.length - i
​
第一次循环结束后  外层循环  i++  内层循环继续比较
​
这样一直执行上述循环操作  直到外层循环结束  输出结果就是最后排好序的数组

实现

 public static void main(String[] args){
        int[] arr = generArray(10);
        bubblSort(arr);
        showArray(arr);
    }
    //冒泡排序
    public static void bubblSort(int[] arr) {
        for (int i = 1; i < arr.length; i++) {  //外层循环
            for (int k = 0; k < arr.length - i; k++) {  //内存循环
                if (arr[k] > arr[k + 1]) {  //满足条件则互换两个元素的值
                    int temp = arr[k + 1];
                    arr[k + 1] = arr[k];
                    arr[k] = temp;
                }
            }
        }
    }
    //定义随机数组
    public static int[] generArray(int len) {
        int[] res = new int[len];
        for (int i = 0; i < res.length; i++) {
            res[i] = (int) (Math.random() * 100);
        }
        return res;
​
    }
    //定义方法  显示输出数组
    public static void showArray(int[] arr) {
        System.out.println(Arrays.toString(arr));
    }

稳定性

在冒泡排序中,遇到相等的值,是不进行交换的,只有遇到不相等的值才进行交换,所以是稳定的

排序方式。

时间复杂度

冒泡排序最好的时间复杂度为O(n)。

适用场景

冒泡排序适用于数据量很小的排序场景,因为冒泡的实现方式较为简单。

快速排序

快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists)

本质上看,快速排序应该算是在冒泡排序基础上的递归分治法

基本操作步骤:

  • 从数组中挑出一个元素,称为基准(pivot)

  • 重新排序数组,所有元素比基准小的放在基准前面,所有元素比基准值大的摆在基准的后边 相同的数可以到任一边。在这个分区退出后,该基准就处于数组的中间位置。这个称为分区(patition)操作

  • 递归(recursive)把小于基准元素的子数列和大于基准元素的子数列排序

具体实现

[4,7,1,8,10,6,5,3,7,9]

pivot = 4 start = 0 end = 9

low = 0   high = 9   pivot = 4 = arr[low]
​
首先从高端部分开始比较,保证高端部分比pivot大。如果值比4大,则high--
high = 7 此时high指针执行的值比pivot小,  arr[low] = arr[high]
[3,7,1,8,10,6,5,3,7,9]  low = 0  high = 7  pivot = 4
​
开始低端比较,从low执行的数据开始进行比较,直到有数据比pivot大为止
如果low指向的数据比pivot小,则low++
low = 1时对应的数据为7,比pivot大,则  arr[high] =  arr[low]
[3,7,1,8,10,6,5,7,7,9]  low = 1  high = 7 pivot = 4
​
一轮比对完成的结束条件应该是low >= high,当前low = 1 < high = 7
​
继续高端比较,比较方式同第一次高端比较
high--  具体值为2,arr[high] < pivot,所有需要赋值
[3,1,1,8,10,6,5,7,7,9]  low = 1 high = 2  pivot = 4
​
继续低端比较low    low++
此时low = high,本次循环结束,回存基准值
[3,1,4,8,10,6,5,7,7,9]  可以发现在4左端的所有数据都比4小,而4右端的数据都比4大
​
---
将原始数组分为2部分继续排序
arr  0----2
arr  3----9
​
以左端为例[3,1,4]
low = 0  high = 2  pivot = 3 = arr[low]
4 > 3 所以high--  low = 0  high = 1
arr[high] < pivot 所以进行修改操作arr[low] = arr[high],所以[1,1,4] low = 0  high = 1
pivot = 3
比较低端,如果值小则low++  low = 1 high = 1  pivot = 3
此时low和high重合,则进行结束循环并赋值[1,3,4]
---
​
重复上述操作                                                                             
                                                                   

具体编码实现

public class Test1 {

	public static void main(String[] args) {
		int[] arr=new int[] {3,7,1,8,10,6,5,3,7,9};
		quickSort(arr, 0, arr.length-1);
		for(int tmp:arr) {
			System.out.print(tmp+"\t");
		}
	}
	public static void quickSort(int[] arr,int start,int end) {
		if(start<end) {
			int pivot=arr[start];
			int low=start;
			int high=end;
			
			while(low<high) {
				while(low<high && arr[high]>=pivot) {
					high--;
				}
				arr[low]=arr[high];
				while(low<high && arr[low]<=pivot) {
					low++;
				}
				arr[high]=arr[low];
			}
			
			arr[low]=pivot;
			quickSort(arr, start, low-1);
			quickSort(arr, low+1, end);   //递归调用自身进行下一次排序
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值