数据结构与算法-归并排序与基数排序


每个人的实现都有不同,重要是掌握其思想。

归并排序

归并排序(MERGE-SORT)是利用归并思想实现的排序方法,该算法采用经典的分治(divide-and-conquer) 策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修 补"在一起,即分而治之)。

基本思想示意图

在这里插入图片描述

归并排序思想示意图 2

合并相邻有序子序列:
再来看看治阶段,我们需要将两个已经有序的子序列合并成一个有序序列,比如上图中的最后一次合并,要将 [4,5,7,8]和[1,2,3,6]两个已经有序的子序列,合并为最终序列[1,2,3,4,5,6,7,8],来看下实现步骤
在这里插入图片描述

应用实例

[8, 4, 5, 7, 1, 3, 6, 2]归并排序完成排序

package my.sort;

import java.util.Arrays;

public class MergeSort {
	public static void main(String[] args) {
		int arr[] = { 8, 4, 5, 7, 1, 3, 6, 2 };
		int temp[] = new int[arr.length];
		mergeSort(arr, 0, arr.length - 1, temp);
		System.out.println("归并排序后=" + Arrays.toString(arr));
	}
	private static void mergeSort(int[] arr,int left,int right,int[] temp) {
		// TODO Auto-generated method stub
		if(left<right) {
			int mid=(left+right)/2;
			mergeSort(arr,left,mid,temp);
			mergeSort(arr,mid+1,right,temp);
			merge(arr,left,mid,right,temp);
		}
	}
	private static void merge(int[] arr, int left, int mid, int right, int[] temp) {
		// TODO Auto-generated method stub
		int i=left;
		int j=mid+1;
		int t=0;
		while(i<=mid && j<=right) {
			if(arr[i]<=arr[j]) {
				temp[t]=arr[i];
				t++;
				i++;
			}else {
				temp[t]=arr[j];
				t++;
				j++;
			}
		}
		while(i<=mid) {
			temp[t]=arr[i];
			t++;
			i++;
		}
		while(j<=right) {
			temp[t]=arr[j];
			t++;
			j++;
		}
		t=0;
		int tempLeft=left;
		while(tempLeft<=right) {
			arr[tempLeft]=temp[t];
			t++;
			tempLeft++;
		}
	}
}

基数排序

  • 基数排序(radix sort)属于“分配式排序”(distribution sort),又称“桶子法”(bucket sort)或 bin sort,顾名思义,它是通过键值的各个位的值,将要排序的元素分配至某些“桶”中,达到排序的作用
  • 基数排序法是属于稳定性的排序,基数排序法的是效率高的稳定性排序法
  • 基数排序(Radix Sort)是桶排序的扩展
  • 将整数按位数切割成不同的数字,然后按每个位数分别比较

基数排序基本思想

  1. 将所有待比较数值统一为同样的数位长度,数位较短的数前面补零。
  2. 然后,从最低位开始,依次进行一次排序。 这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列。

基数排序图文说明

数组 {53, 3, 542, 748, 14, 214} 使用基数排序, 进行升序排序
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码实现

package src.my.sort;

import java.util.Arrays;

public class BasicNumSort {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] arr= {
			10,20,39,200,45,69,320,9,58,
		};
		sort(arr);
	}

	private static void sort(int[] arr) {
		// TODO Auto-generated method stub
		//这是10个桶,每个桶存放数据,每个桶都是一维数组,用来存放数据
		int[][] buckets=new int[10][arr.length];
		//记录每个桶存放了多少个数。
		int[] bucketCounts=new int[10];
		//找出数组的最大值
		int max=0;
		for(int i=0;i<arr.length;i++) {
			if(max<arr[i])max=arr[i];
		}
		//得出最大数的长度
		int length=(max+"").length();
		//1.第一轮排序:按照个位数将每个元素放入不同的桶
		
		//遍历所有数据
		for(int i=0,n=1; i<length;i++,n*=10) {
			int index=0;
			for(int j=0;j<arr.length;j++) {
				//得每个数据的个位数
				int temp=arr[j] / n %10;
				//bucketCounts[temp] :记录temp号桶存放了多少个数据。初始化为0,桶元素数量对应每个桶的元素编号。
				buckets[temp][bucketCounts[temp]]=arr[j];
				//bucketCounts[temp] :记录temp号桶存放了多少个数据,+1 表示该桶有一个数据
				bucketCounts[temp]++;
			}
			//从桶中取出数据
			//遍历每个桶
			for(int j=0; j<bucketCounts.length;j++) {
				//判断桶元素的数量是否为空
				if(bucketCounts[j]!=0) {
					//遍历桶的每一个元素,按顺序存到原来的数组arr中。
					for(int k=0; k<bucketCounts[j];k++) {
						//index:原数组下标
						//k:表示桶的某一个元素
						arr[index]=buckets[j][k];
						index++;
					} 
					bucketCounts[j]=0;
				}
				
			}
			 
		}
		
		System.out.println("第一轮排序后:" + Arrays.toString(arr));
	}

}

基数排序的说明

  1. 基数排序是对传统桶排序的扩展,速度很快.
  2. 基数排序是经典的空间换时间的方式,占用内存很大, 当对海量数据排序时,容易造成 OutOfMemoryError 。
  3. 基数排序时稳定的。[注:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些
    记录的相对次序保持不变,即在原序列中,r[i]=r[j],且 r[i]在 r[j]之前,而在排序后的序列中,r[i]仍在 r[j]之前,
    则称这种排序算法是稳定的;否则称为不稳定的]
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值