排序算法(Java实现)

本文主要讲述八种常见的排序算法,使用Java代码实现
1、冒泡排序
2、选择排序
3、插入排序
4、希尔排序
5、快速排序
6、归并排序
7、堆 排 序
8、桶 排 序
各个排序比较

#1-冒泡排序

1、第一次从0-(lenght-1)两两比较数据,大的沉底到(lenght-1);
2、第二次从0-(lenght-2)两两比较数据,大的沉底(lenght-2);

public class BubbleSort {
	
	public void sort(int[] arr) {
		int temp = 0;
		int n = arr.length;
		for (int i = 0; i < n - 1; i++) {
			for (int j = 0; j < n - 1 - i; j++) {
				if (arr[j] > arr[j + 1]) 
				{
					temp = arr[j];
					arr[j] = arr[j + 1];
					arr[j + 1] = temp;
				}
			}
			System.out.println("第"+(i+1)+"趟:");
			System.out.println(Arrays.toString(arr));
		}
	}
	@Test
	public void test() {
		int[] arr={32,69,58,24,12,36,18,54};
		System.out.println("初始数组:");
		System.out.println(Arrays.toString(arr));
		sort(arr);
	}
}

######结果:
初始数组:
[32, 69, 58, 24, 12, 36, 18, 54]
第1趟:
[32, 58, 24, 12, 36, 18, 54, 69]
第2趟:
[32, 24, 12, 36, 18, 54, 58, 69]
第3趟:
[24, 12, 32, 18, 36, 54, 58, 69]
第4趟:
[12, 24, 18, 32, 36, 54, 58, 69]
第5趟:
[12, 18, 24, 32, 36, 54, 58, 69]
第6趟:
[12, 18, 24, 32, 36, 54, 58, 69]
第7趟:
[12, 18, 24, 32, 36, 54, 58, 69]

改进

不难发现上面的结果从第五趟开始数组已经排好序了,后面的几趟都相当于白操作了;对于冒泡排序,其实我们可以设置一个标志,通过标志判断它是否发生了数据交换,在这一趟里如果未发生数据交换,数组其实就已经排好序了,这时我们break退出循环即可。

public class BubbleSort {
	
	public void sort(int[] arr) {
		int temp = 0;
		int n = arr.length;
		boolean flag=true;
		for (int i = 0; i < n - 1; i++) {
			for (int j = 0; j < n - 1 - i; j++) {
				if (arr[j] > arr[j + 1]) 
				{
					temp = arr[j];
					arr[j] = arr[j + 1];
					arr[j + 1] = temp;
					flag=false;
				}
			}
			if(flag){
				break;
			}
			flag=true;
			System.out.println("第"+(i+1)+"趟:");
			System.out.println(Arrays.toString(arr));
		}
	}
	@Test
	public void test() {
		int[] arr1={32,69,58,24,12,36,18,54};
		System.out.println("初始数组:");
		System.out.println(Arrays.toString(arr));
		sort(arr1);
	}
}

######结果:
初始数组:
[12, 18, 24, 32, 36, 54, 58, 69]
第1趟:
[32, 58, 24, 12, 36, 18, 54, 69]
第2趟:
[32, 24, 12, 36, 18, 54, 58, 69]
第3趟:
[24, 12, 32, 18, 36, 54, 58, 69]
第4趟:
[12, 24, 18, 32, 36, 54, 58, 69]
第5趟:
[12, 18, 24, 32, 36, 54, 58, 69]
#2-选择排序
1、第0位设置为标志位,从后遍历(length-1~1)数组选出最小值,与标志位数据交换;
2、第1位设置为标志位,从后遍历(length-1~2)数组选出最小值,与标志位数据交换;

public class SelectSort {
	public void sort(int[] arr) {
		int n = arr.length; // 数组长度
		int temp = 0; // 中间变量

		for (int i = 0; i < n-1; i++) {
			int k = i;// 待确定的位置
			// 选择出应该在第i个位置的数
			for (int j = n - 1; j > i; j--) {
				if (arr[j] < arr[k]) {
					k = j;
				}
			}
			// 交换两个数
			temp = arr[i];
			arr[i] = arr[k];
			arr[k] = temp;
			
			System.out.println("第"+(i+1)+"趟:");
			System.out.println(Arrays.toString(arr));
		}
	}
	@Test
	public void test(){
		int[] arr = { 32, 69, 58, 24, 12, 36, 18, 54 };
		System.out.println("初始数组:");
		System.out.println(Arrays.toString(arr));
		sort(arr);
	}
}

######结果:
初始数组:
[32, 69, 58, 24, 12, 36, 18, 54]
第1趟:
[12, 69, 58, 24, 32, 36, 18, 54]
第2趟:
[12, 18, 58, 24, 32, 36, 69, 54]
第3趟:
[12, 18, 24, 58, 32, 36, 69, 54]
第4趟:
[12, 18, 24, 32, 58, 36, 69, 54]
第5趟:
[12, 18, 24, 32, 36, 58, 69, 54]
第6趟:
[12, 18, 24, 32, 36, 54, 69, 58]
第7趟:
[12, 18, 24, 32, 36, 54, 58, 69]
#3-插入排序
从前向后遍历数组,用temp记录当前值,假如temp比前面的值小,则将前面的值后移。

public class InsertSort {
	public void sort(int[] arr) {
		int n = arr.length;
		int temp = 0;
		int j = 0;
		for (int i = 0; i < n; i++) {
			temp = arr[i];
			// 假如temp比前面的值小,则将前面的值后移
			for (j = i; j > 0 && temp < arr[j - 1]; j--) {
				arr[j] = arr[j - 1];
			}
			arr[j] = temp;
			System.out.println("第"+(i+1)+"趟:");
			System.out.println(Arrays.toString(arr));
		}
	}
	@Test
	public void test(){
		int[] arr={32,69,58,24,12,36,18,54};
		System.out.println("初始数组:");
		System.out.println(Arrays.toString(arr));
		sort(arr);
	}
}

######结果:
初始数组:
[32, 69, 58, 24, 12, 36, 18, 54]
第1趟:
[32, 69, 58, 24, 12, 36, 18, 54]
第2趟:
[32, 69, 58, 24, 12, 36, 18, 54]
第3趟:
[32, 58, 69, 24, 12, 36, 18, 54]
第4趟:
[24, 32, 58, 69, 12, 36, 18, 54]
第5趟:
[12, 24, 32, 58, 69, 36, 18, 54]
第6趟:
[12, 24, 32, 36, 58, 69, 18, 54]
第7趟:
[12, 18, 24, 32, 36, 58, 69, 54]
第8趟:
[12, 18, 24, 32, 36, 54, 58, 69]
#4-希尔排序
设置每次比较的间隔,间隔相同的数据,两两比较;
间隔–;
直至间隔为1,排序完成;

public class ShellSort {
	public void sort(int[] arr) {
		int j = 0;
		int temp = 0;
		// 每次将步长缩短为原来的一半
		for (int step = arr.length / 2; step > 0; step /= 2) {
			for (int i = step; i < arr.length; i++) {
				temp = arr[i];
				for (j = i; j >= step; j -= step) {
					if (temp < arr[j - step])// 如想从小到大排只需修改这里
					{
						arr[j] = arr[j - step];
					} else {
						break;
					}
				}
				arr[j] = temp;
			}
			System.out.println("STEP:"+step);
			System.out.println(Arrays.toString(arr));
		}
	}
	
	@Test
	public void test(){
		int[] arr={32,69,58,24,12,36,18,54};
		System.out.println("初始数组:");
		System.out.println(Arrays.toString(arr));
		sort(arr);
	}
}

######结果:
初始数组:
[32, 69, 58, 24, 12, 36, 18, 54]
STEP:4
[12, 36, 18, 24, 32, 69, 58, 54]
STEP:2
[12, 24, 18, 36, 32, 54, 58, 69]
STEP:1
[12, 18, 24, 32, 36, 54, 58, 69]
#5-快速排序
选择一个中轴,比它小的放到左边,比它大的放到右边;
然后左边右边继续递归调用,直至排序完成;

public class QuickSort {
	public int count =1;
	public int getMiddle(int[] numbers, int low, int high) {
		int temp = numbers[low]; // 数组的第一个作为中轴
		while (low < high) {
			while (low < high && numbers[high] > temp) {
				high--;
			}
			numbers[low] = numbers[high];// 比中轴小的记录移到低端
			while (low < high && numbers[low] < temp) {
				low++;
			}
			numbers[high] = numbers[low]; // 比中轴大的记录移到高端
		}
		numbers[low] = temp; // 中轴记录到尾
		return low; // 返回中轴的位置
	}

	public void sort(int[] numbers,int low,int high)
    {
        if(low < high)
        {
        	int middle = getMiddle(numbers,low,high); //将numbers数组进行一分为二
        	System.out.println("第"+(count++)+"趟:");
			System.out.println(Arrays.toString(numbers));
        	sort(numbers, low, middle-1);   //对低字段表进行递归排序
        	sort(numbers, middle+1, high); //对高字段表进行递归排序
        }
    
    }
	@Test
	public void test() {
		int[] arr = { 32, 69, 58, 24, 12, 36, 18, 54 };
		System.out.println("初始数组:");
		System.out.println(Arrays.toString(arr));
		sort(arr, 0, arr.length - 1);
	}
}

######结果:
初始数组:
[32, 69, 58, 24, 12, 36, 18, 54]
第1趟:
[18, 12, 24, 32, 58, 36, 69, 54]
第2趟:
[12, 18, 24, 32, 58, 36, 69, 54]
第3趟:
[12, 18, 24, 32, 54, 36, 58, 69]
第4趟:
[12, 18, 24, 32, 36, 54, 58, 69]
#6-归并排序
递归将数据划分为左右两边,直至长度为1;
然后将数据合并,全部合并完成即数组排好了序。

public class MergeSort {
	public void sort(int[] arr, int low, int high) {
		int mid = (low + high) / 2;
		if (low < high) {
			// 左边
			sort(arr, low, mid);
			// 右边
			sort(arr, mid + 1, high);
			// 左右归并
			merge(arr, low, mid, high);
			System.out.println("归并:");
			System.out.println(Arrays.toString(arr));
		}
	}

	public static void merge(int[] arr, int low, int mid, int high) {
		int[] temp = new int[high - low + 1];
		int i = low; // 左指针
		int j = mid + 1;// 右指针
		int k = 0;
		// 把较小的数先移到新数组中
		while (i <= mid && j <= high) {
			if (arr[i] < arr[j]) {
				temp[k++] = arr[i++];
			} else {
				temp[k++] = arr[j++];
			}
		}
		// 把左边剩余的数移入数组
		while (i <= mid) {
			temp[k++] = arr[i++];
		}
		// 把右边边剩余的数移入数组
		while (j <= high) {
			temp[k++] = arr[j++];
		}
		// 把新数组中的数覆盖arr数组
		for (int k2 = 0; k2 < temp.length; k2++) {
			arr[k2 + low] = temp[k2];
		}
	}

	@Test
	public void test() {
		int[] arr = { 69, 32, 58, 24, 39, 36, 54, 18 };
		System.out.println("初始数组:");
		System.out.println(Arrays.toString(arr));
		sort(arr, 0, arr.length - 1);
	}
}

######结果:
初始数组:
[69, 32, 58, 24, 39, 36, 54, 18]
归并:
[32, 69, 58, 24, 39, 36, 54, 18]
归并:
[32, 69, 24, 58, 39, 36, 54, 18]
归并:
[24, 32, 58, 69, 39, 36, 54, 18]
归并:
[24, 32, 58, 69, 36, 39, 54, 18]
归并:
[24, 32, 58, 69, 36, 39, 18, 54]
归并:
[24, 32, 58, 69, 18, 36, 39, 54]
归并:
[18, 24, 32, 36, 39, 54, 58, 69]
#7-堆排序
构建最大堆

public class HeapSort {
	
	public void sort(int[] arr){
		int n = arr.length;
		// 循环建堆
		for (int i = 0; i < n - 1; i++) {
			// 建堆
			buildMaxHeap(arr, n - 1 - i);
			// 交换堆顶和最后一个元素
			swap(arr, 0, n - 1 - i);
			System.out.println("第"+(i+1)+"趟:");
			System.out.println(Arrays.toString(arr));
		}
	}
	
	// 对data数组从0到lastIndex建大顶堆
	public void buildMaxHeap(int[] data, int lastIndex) {
		// 从lastIndex处节点(最后一个节点)的父节点开始
		for (int i = (lastIndex - 1) / 2; i >= 0; i--) {
			// k保存正在判断的节点
			int k = i;
			// 如果当前k节点的子节点存在
			while (k * 2 + 1 <= lastIndex) {
				// k节点的左子节点的索引
				int biggerIndex = 2 * k + 1;
				// 如果biggerIndex小于lastIndex,即biggerIndex+1代表的k节点的右子节点存在
				if (biggerIndex < lastIndex) {
					// 若果右子节点的值较大
					if (data[biggerIndex] < data[biggerIndex + 1]) {
						// biggerIndex总是记录较大子节点的索引
						biggerIndex++;
					}
				}
				// 如果k节点的值小于其较大的子节点的值
				if (data[k] < data[biggerIndex]) {
					// 交换他们
					swap(data, k, biggerIndex);
					// 将biggerIndex赋予k,开始while循环的下一次循环,重新保证k节点的值大于其左右子节点的值
					k = biggerIndex;
				} else {
					break;
				}
			}
		}
	}
	// 交换
	public void swap(int[] data, int i, int j) {
		int tmp = data[i];
		data[i] = data[j];
		data[j] = tmp;
	}

	@Test
	public void test() {
		int[] arr = { 32, 69, 58, 24, 39, 36, 54, 18 };
		System.out.println("初始化数据:");
		System.out.println(Arrays.toString(arr));
		sort(arr);
	}
}

######结果:
初始化数据:
[32, 69, 58, 24, 39, 36, 54, 18]
第1趟:
[18, 39, 58, 24, 32, 36, 54, 69]
第2趟:
[18, 39, 54, 24, 32, 36, 58, 69]
第3趟:
[18, 39, 36, 24, 32, 54, 58, 69]
第4趟:
[18, 32, 36, 24, 39, 54, 58, 69]
第5趟:
[24, 32, 18, 36, 39, 54, 58, 69]
第6趟:
[18, 24, 32, 36, 39, 54, 58, 69]
第7趟:
[18, 24, 32, 36, 39, 54, 58, 69]
#8-桶排序
消耗内存大,一般不建议使用。

public class BucketSort {
	public void sort(int[] arr){
        int n = arr.length;
        List<ArrayList<Integer>> Blist = new ArrayList<>(n);
        for(int i = 0; i < n; i++){
            Blist.add(new ArrayList<Integer>());
        }
        int max = Integer.MIN_VALUE;
        int min = Integer.MAX_VALUE;
        for(int a : arr){
            max = Math.max(max, a);
            min = Math.min(min, a);
        }
        for(int i : arr){
        	int index = (int)((i-min) / (max-min+1.0) * arr.length); 
            Blist.get(index).add(i);
        }
  
        for(int i = 0; i < Blist.size(); i++){
            Collections.sort(Blist.get(i));
        }
        System.out.println(Blist);
        int j = 0;
        for(ArrayList<Integer> list : Blist){
            for(int i : list){
                arr[j++] = i;
            }
        }
	}
	@Test
	public void test(){
        int arr[] = {1,6,6,8,3,5,9,2,1,5};
        System.out.println("初始数组:");
        System.out.println(Arrays.toString(arr));
        sort(arr);
        System.out.println("桶排序:");
        System.out.println(Arrays.toString(arr));
	}
}

######结果:
初始数组:
[1, 6, 6, 8, 3, 5, 9, 2, 1, 5]
[[1, 1], [2], [3], [], [5, 5], [6, 6], [], [8], [9], []]
桶排序:
[1, 1, 2, 3, 5, 5, 6, 6, 8, 9]
#各个排序比较
这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值