数据结构与算法(一)—— 排序(二)

排序(一):https://blog.csdn.net/weixin_56697114/article/details/116431495

目录

1、归并排序

1)递归

2)归并排序

2、快速排序

3、排序的稳定性

排序方式的稳定性:


1、归并排序

1)递归

          定义:定义方法时,在方法内部调用方法本身,称之为递归.

          注意事项:在递归中,不能无限制的调用自己,必须要有边界条件,能够让递归结束,因为每一次递归调用都会在栈内存开辟
新的空间,重新执行方法,如果递归的层级太深,很容易造成栈内存溢出

package paixu;

//求n的阶乘
public class Digui {

	public static void main(String[] args) {
		int sum = suan(5);
		System.out.println(sum);

	}
	
	public static int suan(int n) {
		if(n==1) {
			return 1;
		}
		return n*suan(n-1);
	}

}

2)归并排序

原理:尽可能的一组数据拆分成两个元素相等的子组,并对每一个子组继续拆分,直到拆分后的每个子组的元素个数是
1为止。然后进行排序并合并成新的组,再进行排序合并,直到剩下一个组。

步骤:

1)不断拆分直到每个子组元素个数为1,每两个子组进行比较

2)定义三个指针,i 为assist的指针,p1为第一个子组的指针,p2为第二个子组的指针

3)遍历,通过比较 p1 和 p2 的值,将小的放到assist的 i 中,将小的指针往后移一个格,同时 i 也往后移一个格

4)将assist填充的部分放到 a 中同样的位置

 

package paixu;

import java.util.Arrays;

//归并排序
public class Guib {

	//归并需要的辅助数组
	private static int[] assist;
	
	//对a进行排序
	public static void sort(int[] a) {
		assist = new int[a.length];
		//lo为最小索引,hi为最大索引
		int lo = 0;
		int hi = a.length-1;
		sort(a, lo, hi);
		
	}
	
	//对a从lo到hi进行排序
	public static void sort(int[] a, int lo, int hi) {
		if(hi<=lo) {
			return;
		}
		
		int mid = lo+(hi-lo)/2;
		//对lo到mid进行排序
		sort(a, lo, mid);
		//对mid+1到hi进行排序
		sort(a, mid+1, hi);
		//将两个数组进行归并
		merge(a, lo, mid, hi);
		
	}
	
	public static void merge(int[] a, int lo, int mid, int hi) {
		//定义3个指针
		int i = lo;
		int p1 = lo;
		int p2 = mid+1;
		
		while(p1<=mid && p2<=hi) {
			if(a[p1]<=a[p2]) {
				assist[i++] = a[p1++];
			}else{
				assist[i++] = a[p2++];
			}
		}
		
		while(p1<=mid) {
			assist[i++] = a[p1++];
		}
		while(p2<=hi) {
			assist[i++] = a[p2++];
		}
		
		for(int index=0; index<=hi; index++) {
			a[index] = assist[index];
		}
	}
	
	public static void main(String[] args) {
		int[] a = {6,5,4,3,2,1};
		sort(a);
		System.out.println("结果:"+Arrays.toString(a));

	}
	

}

2、快速排序

原理:O(nlogn)

1)找一个基准值,基准值左边存放比它小的,右边存放比它大的,再定义两个指针  l(左指针) r (右指针)

2)l 从左到右遍历,当发现比基准值大的停止。r 从右到左,当发现比基准值小的停止

3)当 l 和 r 遍历结束后,如果 l<r 就交换两值,再继续遍历直到 l>=r跳出遍历,找到基准值应该在的位置

4)再交换基准值与这个位置的值,返回这个位置的返回值mid

5)根据mid分成两组 lo,mid-1  mid+1,hi,继续以上

package paixu;

import java.util.Arrays;

//快速排序
public class Kuaisu {

	public static void sort(int[] a) {
		
		int lo = 0;
		int hi = a.length-1;
		sort(a, lo, hi);
	}
	
	public static void sort(int[] a, int lo, int hi) {
		if(hi <= lo) {
			return;
		}
		int mid = suan(a,lo,hi);
		
		sort(a, lo, mid-1);
		
		sort(a, mid+1, hi);
	}
	
	public static int suan(int[] a, int lo, int hi) {
		int b = a[lo];
		//定义两个指针
		int l = lo;
		int r = hi;
		while(true) {
			while(a[r]>b) {
				if(r==lo) {
					break;
				}
				r--;
			}
			while(a[l]<=b) {
				if(l==hi) {
					break;
				}
				l++;
			}
			if(l>=r) {
				break;
			}else {
				swap(a, l, r);
			}
			System.out.println(Arrays.toString(a));
		}
		
		swap(a,lo,r);
		return r;
	}
	
	//交换
	public static void swap(int[] a, int i, int j) {
		int temp = a[i];
		a[i] = a[j];
		a[j] = temp;
	}
	
	public static void main(String[] args) {
		int[] a = {6,5,4,3,2,1};
		sort(a);
		System.out.println("结果:"+Arrays.toString(a));

	}

}

3、排序的稳定性

稳定性的定义:
数组arr中有若干元素,其中A元素和B元素相等,并且A元素在B元素前面,如果使用某种排序算法排序后,能够保
证A元素依然在B元素的前面,可以说这个该算法是稳定的。

稳定性的意义: 多次排序才有意义。例,如图,当按销量从高到低排序,如果销量相同时,价格的排序不变,则稳定。

好处:1、保留了价格的排序   2、少进行一次排序,节省资源

排序方式的稳定性:

1)冒泡排序:a[j+1]<a[j]  只有小于时相邻两个才进行判断,所以稳定

2)选择排序:{5(1),8 ,5(2), 2, 9 },排序后{2,5(2),5(1),8,9},5(1)跑到5(2)后面,所以不稳定。

3)插入排序:a[j]>a[j+1],只有大于时相邻两个才会进行交换,所以稳定

4)希尔排序:{5(1),8 ,5(2), 2, 9 },排序后{2,5(2),5(1),8,9},5(1)跑到5(2)后面,所以不稳定。

5)归并排序: 当等于的时候前面的还是放在前面,所以稳定。

6)快速排序:在基准值的右侧找一个比基准值小的元素,在基准值的左侧找一个比基准值大的元素,然后交换这两个元素,是不稳定的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值