Java_排序算法

Java数据结构和算法

冒泡排序BubbleSort

冒泡排序(Bubble Sorting)的基本思想:通过对待排序序列从前向后(从下标较小的元素开始),依次比较相邻元素的值,若发现逆序则交换,使值较大的元素逐渐从前移向后部。

优化:因为排序的过程中,各元素不断接近自己的位置,如果一趟比较下来,没有进行过交换,就说明序列有序,因此要在排序过程中设置一个标志flag判断元素是否进行过交换。从而减少不必要的比较。

import java.util.Arrays;

/**
 * 
 * @Description 冒泡排序,O(n^2)
 * @author 岳昌宏
 * @version
 * @data 2022年2月8日上午11:44:12
 */
public class BubbleSort {
	public static void main(String[] args) {
		int[] arr = new int[] {3, 2, 5, 1, 6, 2, 4};
		
		boolean flag = false;
		for (int i = 0; i < arr.length - 1; i++) {
			for (int j = 0; j < arr.length - 1 - i; j++) {
				if (arr[j] > arr[j+1]) {
					flag = true;
					arr[j] = arr[j] ^ arr[j+1];
					arr[j+1] = arr[j] ^ arr[j+1];
					arr[j] = arr[j] ^ arr[j+1];
				}
			}
			
			if (!flag) { // 在一次排序中,一次交换都没有发生
				break;
			}else {
				flag = false;
			}
		}
		
		System.out.println(Arrays.toString(arr));
	}
}

选择排序SelectSort

选择式排序也属于内部排序法,是从欲排序的数据中,按指定的规则选择出某一个元素,再依规定交换位置后达到排序的目的。

选择排序(select sort)也是一种简单的排序方法。它的基本思想是:第一次从arr[0]arr[n-1]中选取最小值,与arr[0]交换,第二次从arr[1]arr[n-1]中选取最小值,与arr[1]交换…总共通过n-1次,得到一个按排序码从小到大排序的有序序列。

import java.util.Arrays;

/**
 * 
 * @Description 选择排序, O(n^2)
 * @author 岳昌宏
 * @version
 * @data 2022年2月8日下午6:09:22
 */
public class SelectSort {
	public static void main(String[] args) {
		int[] arr = new int[] {1, 4, 12, 76 ,2, -2};
		
		for (int i = 0; i < arr.length - 1; i++) {
			int mindex = i; // 记录最小值下标
			int min = arr[i]; // 记录最小值
			for (int j = i + 1; j < arr.length; j++) {
				if (arr[j] < min) {
					min = arr[j];
					mindex = j;
				}
			}
			if (mindex != i) {
				arr[mindex] = arr[i];
				arr[i] = min;
			}
			
		}
		
		System.out.println(Arrays.toString(arr));
	}
}

插入排序InsertionSort

插入排序(Insertion Sorting)的基本思想:把n个待排序的元素看成为一个有序表和一个无序表,开始时有序表中只包含一个元素,无序表中包含n-1个元素,排序过程中每次从无序表中取出第一个元素,把它的排序码依次与有序表的排序码进行比较,将它插入到有序表中的适当位置,使之成为新的有序表。

import java.util.Arrays;

/**
 * 
 * @Description 插入排序
 * @author 岳昌宏
 * @version
 * @data 2022年2月9日上午10:13:43
 */
public class InsertSort {
	public static void main(String[] args) {
		int[] arr = new int[] {1, 4, 12, 76 ,2, -2};
		
		for (int i = 1; i < arr.length; i++) { // 从第二位开始插入
			int insertNumber = arr[i]; // 待插入数
			int insertIndex = i-1; // 有序列表最大下标
			while (insertIndex >= 0 && arr[insertIndex] > insertNumber) {
				arr[insertIndex + 1] = arr[insertIndex]; // 向前挪一位
				insertIndex--; // 判断下一位
			}
			arr[insertIndex + 1] = insertNumber;
		}
		
		System.out.println(Arrays.toString(arr));
	}
}

希尔排序ShellSort

希尔排序是希尔于1959年提出的一种排序算法。希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序

希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减少至1时,整个文件恰被分为一组,算法便终止。

import java.util.Arrays;

/**
 * 
 * @Description 希尔排序 -- 交换法
 * @author 岳昌宏
 * @version
 * @data 2022年2月9日上午11:17:43
 */
public class ShellSort {
	public static void main(String[] args) {
		int[] arr = new int[] {8, 9, 1, 7, 2, 3, 5, 4, 6, 0};
		
		for (int group = arr.length / 2 ; group > 0; group = group / 2) { // 分组
			for (int i = group; i < arr.length; i++) {
				for (int j = i - group; j >= 0; j = j -group) {
					if (arr[j] > arr[j+group]) {
						arr[j] = arr[j] ^ arr[j+group];
						arr[j+group] = arr[j] ^ arr[j+group];
						arr[j] = arr[j] ^ arr[j+group];
					}
				}
			}
		}
		
		System.out.println(Arrays.toString(arr));
	}
}
import java.util.Arrays;

/**
 * 
 * @Description 希尔排序 --- 位移法
 * @author 岳昌宏
 * @version
 * @data 2022年2月9日上午11:17:43
 */
public class ShellSort {
	public static void main(String[] args) {
		int[] arr = new int[] {8, 9, 1, 7, 2, 3, 5, 4, 6, 0};
		
		for (int group = arr.length / 2; group > 0; group = group / 2) {
			for (int i = group; i < arr.length; i++) {
				int j = i; // 要插入元素的下标
				int temp = arr[j]; // 要插入的元素
				while (j - group >= 0 && temp < arr[j - group]) {
					// 移动
					arr[j] = arr[j- group];
					j = j - group;
				}
				arr[j] = temp;
			}
		}
		
		System.out.println(Arrays.toString(arr));
	}
}

快速排序QucikSort_递归

快速排序是对冒泡排序的一种改进,基本思想:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据小,然后再按此方法对两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

import java.util.Arrays;

/**
 * 
 * @Description 快速排序
 * @author 岳昌宏
 * @version
 * @data 2022年2月9日下午2:30:34
 */
public class QuickSort {
	public static void main(String[] args) {
		int[] arr = new int[] {8, 9, 1, 7, 2, 3, 5, 4, 6, 0};
		
		quickSort(arr, 0, arr.length-1);
		
		System.out.println(Arrays.toString(arr));
		
	}
	
	public static void quickSort(int[] arr, int left, int right) {
		int l = left; // 左下标
		int r = right; // 右下标
		int pivot = arr[(left + right) / 2]; // 中间值
		
		while (l < r) {
			// 在pivot的左边一直找,找到大于等于pivot的值,才退出
			while(arr[l] < pivot) {
				l++;
			}
			while(arr[r] > pivot) {
				r--;
			}
			/**
			 * 出现这种可能是,pivot的左边的值都比pivot的小,l找到了pivot的右边
			 */
			if (l >= r) { 
				break;
			}
			
			// 交换
			arr[l] = arr[l] ^ arr[r];
			arr[r] = arr[l] ^ arr[r];
			arr[l] = arr[l] ^ arr[r];
			
			/**
			 * 思考思考:设计很巧妙
			 * 放置进入死循环
			 */
			// 如果交换完后,发现arr[l] == pivot值
			if (arr[l] == pivot) {
				r--;	
			}
			if (arr[r] == pivot) {
				l++;
			}
		}
		
		/**
		 * 如果l == r
		 */
		 if (l == r) {
			 l++;
			 r--;
		 }
		 
		 /**
		  * 向左递归
		  */
		 if (left < r) {
			 quickSort(arr, left , r);
		 } 
		 /**
		  * 向右递归
		  */
		 if (right > l) {
			 quickSort(arr, l, right);
		 }
	}
}

归并排序MergeSort_递归

import java.util.Arrays;

/**
 * 
 * @Description 归并排序
 * @author 岳昌宏
 * @version
 * @data 2022年2月9日下午8:59:22
 */
public class MergeSort {
	public static void main(String[] args) {
		int[] arr = new int[] {8, 4, 5, 7, 1, 3, 6, 2};
		
		mergeSort(arr, 0, arr.length-1, new int[arr.length]);
		
		System.out.println(Arrays.toString(arr));
	}
	
	
	
	
	public static void mergeSort(int[] arr, int left, int right, int[] temp) {
		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);
		}
	}
	/**
	 * 合并的方法
	 * @param arr 排序的原始数组
	 * @param left 左边有序序列的初始索引
	 * @param mid 中间索引
	 * @param right 右边索引
	 * @param temp 中转的数组
	 */
	public static void merge(int[] arr, int left, int mid, int right, int[] temp) {
		int i = left; // 初始化i,左边有序队列的初始索引
		int j = mid + 1; // 初始化j,右边有序序列的初始索引
		int t = 0; // 指向temp数组的当前索引
		
		// 1.先把左右两端的数据按照规则填充到temp中,直到左右两边有序序列有一边处理完毕为止
		while(i <= mid && j <= right) {
			if (arr[i] <= arr[j]) {
				temp[t] = arr[i];
				t++;
				i++;
			}else {
				temp[t] = arr[j];
				t++;
				j++;
			}
		}
		// 2.把有剩余数据的一边的数据依次全部到填充到temp去
		while(i <= mid) {
			temp[t] = arr[i];
			i++;
			t++;
		}
		while(j <= right) {
			temp[t] = arr[j];
			j++;
			t++;
		}
		
		// 3.将temp数组拷贝到arr
		t = 0;
		int tempLeft = left;
		while(tempLeft <= right) {
			arr[tempLeft] = temp[t];
			t++;
			tempLeft++;
		}
		
	}
}

基数排序(桶排序)

基本思想:将所有待比较数值统一为同样的数位长度,数位较短的数前面补零。然后从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后,数列就变成了一个有序序列。稳定性,如果有负数,需要对代码进行改变

import java.util.Arrays;

/**
 * 
 * @Description 基数排序
 * @author 岳昌宏
 * @version
 * @data 2022年2月10日上午11:31:20
 */
public class RadixSort {
	public static void main(String[] args) {
		int[] arr = new int[] {53, 3, 542, 748, 14, 214};
		
		radixSort(arr);
		
		System.out.println(Arrays.toString(arr));
		
	}
	
	public static void radixSort(int[] arr) {
		// 定义一个二维数组,表示10个桶
		int[][] bucket = new int[10][arr.length];
		// 为了记录每个桶中,实际存放了多少个数据,我们定义一个一维数组来记录各个桶每次放入的个数
		int[] bucketElementCounts = new int[10];
		
		int max = arr[0];
		for (int i = 1; i < arr.length; i++) {
			if (arr[i] > max) {
				max = arr[i];
			}
		}
		
		for (int i = 0, n = 1; i < String.valueOf(max).length() ; i++, n = n * 10) {
			for (int j = 0; j < arr.length; j++) {
				int digitOfElement = arr[j] / n % 10; // 位

				bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
				bucketElementCounts[digitOfElement]++;
			}
			int index = 0;
			for (int k = 0; k < bucketElementCounts.length; k++) {
				if (bucketElementCounts[k] != 0) {
					for (int l = 0; l < bucketElementCounts[k]; l++) {
						// 取出元素
						arr[index] = bucket[k][l];
						index++;
					}
				}
				bucketElementCounts[k] = 0;
			} 
		}
		
	}
}

堆排序

import java.util.Arrays;

/**
 * 
 * @Description 堆排序
 * @author 岳昌宏
 * @version
 * @data 2022年2月17日下午5:45:05
 */
public class HeapSort {
	public static void main(String[] args) {
		int[] arr = new int[] {4, 6, 8, 5, 9};
		
		headSort(arr);
		
		System.out.println(Arrays.toString(arr));
	}
	
	// 堆排序
	public static void headSort(int[] arr) {
		for (int i = arr.length / 2-1; i >=0; i--) { // 非叶子节点
			adjustHeap(arr, i, arr.length);
		}
		
		for(int j = arr.length-1; j > 0; j--) {
			// 交换
			arr[0] = arr[j] ^ arr[0];
			arr[j] = arr[j] ^ arr[0];
			arr[0] = arr[j] ^ arr[0];
			
			adjustHeap(arr, 0, j);
		}
	}
	
	// 将一个数组(二叉树),调整成一个大顶堆
	/**
	 * 
	 * @param arr 待调整的数组
	 * @param i 非叶子节点在数组中的索引
	 * @param length 对多少个元素进行调整,length是在逐渐减少的
	 */
	public static void adjustHeap(int[] arr, int i, int length) {
		int temp = arr[i]; // 先取出当前临时变量的值
		// 开始调整
		for (int k = i*2+1; k < length; k = k*2+1) {
			if (k+1 < length && arr[k] < arr[k+1]) { // 说明左子节点的值小于右子节点的值
				k++; // k就指向右子节点
			}
			if (arr[k] > temp) { // 如果子节点大于父节点
				arr[i] = arr[k]; // 把较大的值赋给当前节点
				i = k; // 让i指向k,继续循环比较
			}else {
				break;
			}
		}
		// 当for循环结束宏,我们已经将i为父节点的树的最大值,放在了最顶上
		arr[i] = temp;
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值