算法1:冒泡算法
(1)该算法遵循交换排序的思想,简单稳定。
(2)原理:逐趟进行两两比较,小的一方往前排。
(3)算法代码实现:
public class ArrayTest01 {
public static void main(String[] args) {
int[] arr = {1, 5, 34, 2, 53, 67};
//冒泡排序
bubbleSort(arr);
}
public static void bubbleSort(int[] arr) {
int temp = 0;
for(int i=arr.length-1; i>0; i--) {
for(int j=0; j<i; j++) {
if(arr[j] > arr[j+1]) {
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
System.out.println(Arrays.toString(arr));
}
}
算法2:快速排序
(1)该算法采用“分而治之”的思想,把大的拆分为小的,小的再拆分为更小的,高效但不稳定。
(2)原理:在已知需排列的序列中,先找一个固定的比较对象,通过一趟排序后,将原序列分为两部分,比固定的比较对象小的归为一部分,放前边,比固定的比较对象大的归为一部分,放后边,然后递归该过程,直到序列中所有记录均为有序为止。
(3)算法代码实现:
public class ArrayTest01 {
public static void main(String[] args) {
int[] arr = {1, 5, 34, 2, 53, 67};
//快速排序
sort(arr, 0, arr.length-1);
}
public static void sort(int[] arr, int low, int high) {
quickSort(arr, low, high);
System.out.println(Arrays.toString(arr));
}
public static void quickSort(int[] arr, int low, int high) {
if(low >= high)
return;
int start = low;
int end = high;
int temp = arr[low]; //视为固定的比较对象
while(low < high) {
while(low < high && arr[high] >= temp)
high--;
arr[low] = arr[high];
while(low < high && arr[low] <= temp)
low++;
arr[high] = arr[low];
}
arr[low] = temp; //将固定的对象放回本趟排序后的low的位置,否则将会丢失该对象
quickSort(arr, start, low-1);
quickSort(arr, low+1, end);
}
}
算法3:插入排序
(1)该算法简单直观稳定,适用对数据量小的序列排序。
(2)原理:一个待排序的序列,默认第一个元素已经被排序,取下一个元素,在已经排好序的序列中从后向前扫描,直到找到已排序的元素小于或等于新元素的位置,将新元素插入。
(3)算法代码实现:
public class ArrayTest01 {
public static void main(String[] args) {
int[] arr = {1, 5, 34, 2, 53, 67};
//插入排序
insertSort(arr);
}
public static void insertSort(int[] arr) {
for(int i=1; i<arr.length; i++) {
int temp = arr[i]; //取出的元素
int j;
for(j=i-1; j>=0 && temp<arr[j]; j--)
arr[j+1] = arr[j]; //从后向前扫描,取出的元素小往前放
arr[j+1] = temp; //直到找到已排序的元素小于或等于新元素的位置,将取出元素插入||取出的元素大,直接放排好的序列后面
}
System.out.println(Arrays.toString(arr));
}
}
算法4:选择排序
(1)该算法简单直观但不稳定。
(2)原理:在未排序序列中,每一趟都找出最小的依次排到有序队列的末尾,直到所有元素均排序完成。
(3)算法代码实现:
public class ArrayTest01 {
public static void main(String[] args) {
int[] arr = {1, 5, 34, 2, 53, 67};
//选择排序
selectSort(arr);
}
public static void selectSort(int[] arr) {
for(int i=0; i<arr.length; i++) {
int k = i;
//循环结束即可找出本趟序列的最小值
for(int j=i+1; j<arr.length; j++) {
if(arr[k] > arr[j])
k = j;
}
//把内循环找出的最小值放至有序队列末尾
if(k != i) {
int temp = arr[i];
arr[i] = arr[k];
arr[k] = temp;
}
}
System.out.println(Arrays.toString(arr));
}
}
算法5:希尔(shell)排序
(1)该算法是插入排序中的一种但不稳定,也被称为“缩小增量排序”。
(2)原理:先根据缩小增量的原则将待排的序列分为若干子序列,然后依次对子序列直接进行插入排序,即可完成排序。
(3)算法代码实现:
public class ArrayTest01 {
public static void main(String[] args) {
//希尔排序
shellSort(arr);
}
/**
* 1、假设待排序列有n个元素,增量遵循(n/2, (n/2)/2, ((n/2)/2)/2, ...)方式缩小,直到为1;
* 2、根据每次的增量,使待排序列直接进行插入排序实现跳跃式移动,本程序缩小增量为3,1.
* @param arr
*/
public static void shellSort(int[] arr) {
int i,j;
int h; //增量
//根据缩小增量划分待排子序列
for(h=arr.length/2; h>0; h/=2) {
//待排子序列分别进行插入排序
for(i=h; i<arr.length; i++) {
int temp = arr[i]; //取出的元素
for(j=i-h; j>=0; j-=h) {
if(temp < arr[j]) {
arr[j+h] = arr[j]; //小的元素往前放
}else {
break; //本次待排序列已排序完毕
}
}
arr[j+h] = temp; //直到找到已排序的元素小于或等于新元素的位置,将取出元素插入||取出的元素大,直接放排好的序列后面
}
}
System.out.println(Arrays.toString(arr));
}
}
算法6:归并排序
(1)该算法采用递归与分治技术,高效稳定。
(2)原理:给定一待排序序列(假设n个元素),首先将每两个相邻的长度为1的子序列进行归并,得到n/2(向上取整)个长度为2或1的有序子序列,再将其两两归并,反复执行此过程,直到得到一个有序序列。
(3)算法代码实现:
public class ArrayTest01 {
public static void main(String[] args) {
int[] arr = {1, 5, 34, 2, 53, 67};
//归并排序
mergeDesc(arr);
}
/**
* 1、利用递归与分治法将待排序序列划分成越来越小的半子表,再对半子表进行排序(划分半子表);
* 2、最后用递归方法将排好序的半子表合并成为越来越大的有序序列(合并半子表)。
* @param arr
* @param start
* @param end
*/
public static int[] mergeSort(int[] arr, int start, int end) {
if(start < end) {
int mid = (start + end)/2; //分治法
mergeSort(arr, start, mid); //递归排序
mergeSort(arr, mid+1, end);
int[] afterArr = merge(arr, start, mid, mid+1, end);
return afterArr;
}
return null;
}
//归并排序
public static int[] merge(int[] arr, int start, int mid, int mid1, int end) {
int[] temp = new int[end - start + 1]; //用来存放排好序的序列
int k = 0;
while(start <= mid && mid1 <= end) {
if(arr[start] < arr[mid1])
temp[k++] = arr[start++];
else
temp[k++] = arr[mid1++];
}
while(start <= mid) {
temp[k++] = arr[start++];
}
while(mid1 <= end) {
temp[k++] = arr[mid1++];
}
arr = Arrays.copyOf(temp, temp.length); //把排好序的序列替换以前的序列
return arr;
}
//显示归并后的序列信息
public static void mergeDesc(int[] arr) {
int[] finishArr = mergeSort(arr, 0, arr.length-1);
System.out.println(Arrays.toString(finishArr));
}
}
算法7:堆排序
(1)该算法是一树形选择排序,不稳定,通常提到的堆都是指一棵完全二叉树,它分为大顶堆和小顶堆两种不同的类型。
(2)原理:首先利用完全二叉树中父节点和子节点之间的内在关系将待排序序列构造成初始堆(若想升序则建立大顶堆,想降序则建立小顶堆),然后将堆顶的根节点与堆的末尾元素交换,最后将剩余的序列重新构成一个堆。如此反复执行,即可得到有序序列。
(3)算法代码实现:
public class ArrayTest01 {
public static void main(String[] args) {
int[] arr = {1, 5, 34, 2, 53, 67};
//堆排序
heapSort(arr);
}
/**
* 1、创建大顶堆,使得根节点大于子节点。
* 2、将堆顶根节点与堆的末尾节点交换。
* @param arr
*/
public static void heapSort(int[] arr) {
createMaxHeap(arr);
for(int i=arr.length-1; i>0; i--) { //完成大顶堆的初始化后,进行堆顶元素与最后一个元素(从平衡二叉树的最后一个节点开始)交换
int temp = arr[0];
arr[0] = arr[i];
arr[i] = temp;
maxHeap(arr, 1, i); //顶堆元素完成交换后成为无序状态,继续构造大顶堆
}
System.out.println(Arrays.toString(arr));
}
//创建大顶堆
public static void createMaxHeap(int[] arr) {
int startNode = arr.length/2; //父节点
for(int i=startNode; i>0; i--) { //根据平衡二叉树非叶子结点的根节点开始一直到顶端根节点
maxHeap(arr, i, arr.length);
}
}
//构造大顶堆
public static void maxHeap(int[] arr, int startNode, int length) {
int leftNode = 2 * startNode; //左孩子
int rightNode = 2 * startNode + 1; //右孩子
int maxNode = startNode; //节点大值初始化为父节点
if(leftNode <= length && arr[leftNode-1] > arr[startNode-1]) { //左孩子的值大于父节点的值,则交换值
maxNode = leftNode;
}
if(rightNode <= length && arr[rightNode-1] > arr[maxNode-1]) { //右孩子的值大于父节点的值,则交换值
maxNode = rightNode;
}
//通过左右孩子与父节点的比较,如果大值有改变,父节点与孩子节点进行交换
if(maxNode != startNode) {
int temp = arr[startNode-1];
arr[startNode-1] = arr[maxNode-1];
arr[maxNode-1] = temp;
maxHeap(arr, maxNode, length);
}
}
}