顺序查找(Linear Search)是一种在有序数组中查找目标元素的基本算法。它的时间复杂度为 O(n),适用于查找少量数据。顺序查找的基本思想是从数组的第一个元素开始,逐个与待查找的元素进行比较,直到找到目标元素或遍历完整个数组。
package com.zhx;
public class Test {
//顺序查找
public static int seqSearch(int[] array, int target) {
for (int i = 0; i < array.length; i++) {
int p = array[i];
if (p == target) {
System.out.println("sucess to find out "+target+" from array, index="+i);
return i;
}
}
System.out.println("fail to find out the target");
return -1;
}
public static void main(String[] args) {
int[] data = { 3, 6, 7, 2, 12, 9, 0, 11 };
System.out.println(seqSearch(data, 12));
}
}
package com.zhx;
public class Test1 {
//折半查找
public static int seqSearch(int[] array, int target) {
int lo = 0;
int hi = array.length - 1;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
if (target < array[mid]) {
hi = mid - 1;
} else if (target > array[mid]) {
lo = mid + 1;
} else {
return mid;
}
}
return -1;
}
public static void main(String[] args) {
int[] data = { 10, 11, 12, 16, 18, 23, 29, 33, 48, 54, 57, 68, 77, 84, 98 };
System.out.println(seqSearch(data, 23));
}
}
import java.util.Arrays;
public class Test {
public static void bubbleSort(int[] arr) {
for (int i = 1; i < arr.length; i++) {
// i=1, j=4
// i=2, j=3
// i=3, j=2
// j=arr.length-1-i
for (int j = 0; j <= arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
public static void main(String[] args) {
int[] arr = { 9, 8, 5, 4, 2, 0 };
bubbleSort(arr);
System.out.println(Arrays.toString(arr));
}
}
快速排序(Quick Sort)是一种分治策略(Divide and Conquer)的排序算法。它通过选取一个基准元素(pivot),将数组分为两个子数组,其中一个子数组的元素都小于基准元素,另一个子数组的元素都大于基准元素。然后对这两个子数组分别进行递归排序。当整个数组所有元素有序时,排序完成。
package com.zhx;
import java.util.Arrays;
public class QuickSort {
public static void quickSort(int[] arr, int low, int high) {
if (low < high) {
// 1. 定义基准pivot,
int pivot = arr[low];
// ...... pivot移动到中间,左边都比pivot小,后边都比pivot大, index
int i = low;
int j = high;
while (i < j) {
while (i < j && arr[j] >= pivot) {
j--;
}
// 交换
swap(arr, i, j);
while (i < j && arr[i] <= pivot) {
i++;
}
// 交换
swap(arr, i, j);
}
// 2. 递归对左右2部分快排
quickSort(arr, low, j - 1);
quickSort(arr, j + 1, high);
}
}
public static void swap(int arr[], int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public static void main(String[] args) {
int[] arr = { 5, 3, 7, 6, 4, 1, 0, 2, 9, 10, 8 };
quickSort(arr, 0, arr.length - 1);
System.out.println(Arrays.toString(arr));
}
}
package com.zhx;
import java.util.Arrays;
public class SortTest {
public static void InsertSort(int[] arr) {
for (int i = 1; i < arr.length; i++) {
for (int j = i; j > 0; j--) {
if (arr[j] < arr[j - 1]) {
int temp = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = temp;
} else {
break;
}
}
}
}
public static void main(String[] args) {
int[] arr = { 7, 6, 9, 3, 1, 5, 2, 4 };
InsertSort(arr);
System.out.println(Arrays.toString(arr));
}
}
希尔排序(Shell Sort)是一种插入排序的算法,它的主要思想是使数组中任意间隔为 h 的元素都是有序的。这样的数组被称为 h 有序数组。希尔排序会不断减小 h 的值,直到最后 h=1 时,所有元素就都是有序的了。
package com.zhx;
import java.util.Arrays;
public class SortTest {
public static void shellSort(int[] arr) {
// 增量gap, 并逐步的缩小增量
for (int gap = arr.length / 2; gap > 0; gap /= 2) {
// 从第gap个元素,逐个对其所在的组进行直接插入排序
for (int i = gap; i < arr.length; i++) {
for (int j = i; j >= gap; j -= gap) {
if (arr[j] < arr[j - gap]) {
int temp = arr[j];
arr[j] = arr[j - gap];
arr[j - gap] = temp;
} else {
break;
}
}
}
}
}
public static void main(String[] args) {
int[] arr = { 8, 9, 1, 7, 2, 3, 5, 4, 6, 0 };
shellSort(arr);
System.out.println(Arrays.toString(arr));
}
}
package com.zhx;
import java.util.Arrays;
public class SortTest {
//选择排序
public static void selectionSort(int[] arr) {
int len = arr.length;
int minIndex, temp;
for (int i = 0; i < len - 1; i++) { //最后一个数不用排序
minIndex = i;
for (int j = i + 1; j < len; j++) {
if (arr[j] < arr[minIndex]) { // 寻找最小的数
minIndex = j; // 将最小数的索引保存
}
}
temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
public static void main(String[] args) {
int[] arr = { 29, 38, 65, 87, 78, 23, 27, 29 };
selectionSort(arr);
System.out.println(Arrays.toString(arr));
}
}
堆排序(Heap Sort)是一种基于二叉堆(Binary Heap)的选择排序算法。它的基本思想是:将待排序的序列构造成一个大顶堆(或小顶堆),此时整个序列的最大值(或最小值)就是堆顶的根节点。然后将其与末尾元素进行交换,得到当前最大(或最小)值。接着调整剩余元素,使其满足堆的性质,然后继续重复这个过程,直到所有元素排好序。
大顶堆(Big Heap)和小顶堆(Little Heap)是两种不同的堆结构,它们在计算机科学中有着广泛的应用。
大顶堆:在大顶堆中,每个节点都大于或等于其子节点。换句话说,大顶堆满足以下条件:
对于任意的节点 i,有 arr[i] >= arr[2 * i] 和 arr[i] >= arr[2 * i + 1]。
小顶堆:在小顶堆中,每个节点都小于或等于其子节点。换句话说,小顶堆满足以下条件:
对于任意的节点 i,有 arr[i] <= arr[2 * i] 和 arr[i] <= arr[2 * i + 1]。
大顶堆和小顶堆的主要区别在于节点之间的顺序关系。大顶堆的特点是父节点大于子节点,而小顶堆的特点是父节点小于子节点。
在 Java 编程中,我们可以使用数组来表示堆结构。对于大顶堆,我们可以使用以下方法维护堆性质:
package com.zhx;
import java.util.Arrays;
public class HeapSort {
public static void main(String[] args) {
int[] arr = { 27, 46, 12, 33, 49, 27, 36, 40, 42, 50, 51 };
heapSort(arr);
System.out.println(Arrays.toString(arr));
}
public static void heapSort(int[] arr) {
// 建最大堆(arr数组本身就可以看做是一个二叉堆,下面需要将arr变成一个最大堆)
/*
* 1、第一个非叶子节点的下标为:arr.length/2-1
* 2、从第一个非叶子节点开始,遍历每一个非叶子节点,使它们都成为最大堆
*/
for (int i = arr.length / 2 - 1; i >= 0; i--) {
heapify(arr, i, arr.length - 1);
}
for (int i = arr.length - 1; i > 0; i--) {
//将arr数组的第一个元素(因为此元素是最大堆顶点)与数组最后一个元素交换(因为是升序)
swap(arr, 0, i);
//交换之后arr不是最大堆了(i已经排好序了,不用考虑)
heapify(arr, 0, i - 1);
}
}
//将i节点变成一个最大堆
public static void heapify(int[] arr, int i, int last_index) {
int max = i;
if (2 * i + 1 <= last_index && arr[2 * i + 1] > arr[max]) {
max = 2 * i + 1;// max记为左节点
}
if (2 * i + 2 <= last_index && arr[2 * i + 2] > arr[max]) {
max = 2 * i + 2;// max记为右节点
}
if (max != i) {
// 将i节点与它的最大子节点进行交换
swap(arr, max, i);
// 递归对调用的子节点进行heapify
heapify(arr, max, last_index);
}
}
public static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
package com.zhx;
import java.util.Arrays;
public class MergeSort {
public static void mergeSort(int arr[], int[] temp, int low, int high) {
if (low < high) {
// 分2部分
int mid = (low + high) / 2;
// 1. 对左边进行归并排序
mergeSort(arr, temp, low, mid);
// 2. 对右边进行归并排序
mergeSort(arr, temp, mid + 1, high);
// 3. 合并左右两个有序集合
merge(arr, temp, low, mid, high);
}
}
public static void merge(int[] arr, int[] temp, int low, int mid, int high) {
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++];
}
}
// 左边有剩余,将左边剩余的填入temp
while (i <= mid) {
temp[k++] = arr[i++];
}
// 右边有剩余,将右边剩余的填入temp
while (j <= high) {
temp[k++] = arr[j++];
}
// 将临时数组,从头开始拷贝到arr中
k = 0;
while (low <= high) {
arr[low++] = temp[k++];
}
}
public static void main(String[] args) {
int[] arr = { 8, 4, 5, 7, 1, 3, 6, 2 };
// 辅助数组
int[] temp = new int[arr.length];
mergeSort(arr, temp, 0, arr.length - 1);
System.out.println(Arrays.toString(arr));
}
}
package com.zhx;
import java.util.Arrays;
public class CountSort {
public static void countSort(int[] arr) {
// 找到最大值
int max = arr[0];
for (int i = 0; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
// 找到最小值
int min = arr[0];
for (int i = 0; i < arr.length; i++) {
if (arr[i] < min) {
min = arr[i];
}
}
// 创建计数数组
int[] count = new int[max - min + 1];
for (int i = 0; i < arr.length; i++) {
count[arr[i] - min]++;
}
int k = 0;
// 往数组中输出
for (int i = 0; i < count.length; i++) {
while (count[i] > 0) {
arr[k++] = i + min;
count[i]--;
}
}
}
public static void main(String[] args) {
int[] arr = { 108, 109, 106, 101, 107, 102, 103, 102, 104, 106, 101, 110 };
countSort(arr);
System.out.println(Arrays.toString(arr));
}
}
package com.zhx;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collections;
public class BucketSort {
public static void bucketSort(int[] arr) {
// 找到数组的最大值
int max = arr[0];
for (int i = 0; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
// 找到数组的最小值
int min = arr[0];
for (int i = 0; i < arr.length; i++) {
if (arr[i] < min) {
min = arr[i];
}
}
// 创建桶的容器
ArrayList<ArrayList<Integer>> list = new ArrayList<>();
// 确定桶的数量
int count = (max - min) / arr.length + 1;
for (int i = 0; i < count; i++) {
list.add(new ArrayList<Integer>());
}
// 往桶里放
for (int i = 0; i < arr.length; i++) {
list.get((arr[i] - min) / arr.length).add(arr[i]);
}
// 给每个桶排序
for (int i = 0; i < list.size(); i++) {
Collections.sort(list.get(i));
}
// 把桶里的内容输出
int k = 0;
for (int i = 0; i < list.size(); i++) {
ArrayList<Integer> bucket = list.get(i);
for (int j = 0; j < bucket.size(); j++) {
arr[k++] = bucket.get(j);
}
}
}
public static void main(String[] args) {
int[] arr = { 3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48 };
bucketSort(arr);
System.out.println(Arrays.toString(arr));
}
}
package com.zhx;
import java.util.Arrays;
public class RadixSort {
public static void main(String[] args) {
int[] arr = {26,3,49,556,81,9,863,0};
radixSort(arr);
System.out.println(Arrays.toString(arr));
}
private static void radixSort(int[] arr) {
//待排序列最大值
int max = arr[0];
int exp;//指数
//计算最大值
for (int anArr : arr) {
if (anArr > max) {
max = anArr;
}
}
//从个位开始,对数组进行排序
for (exp = 1; max / exp > 0; exp *= 10) {
//存储待排元素的临时数组
int[] temp = new int[arr.length];
//分桶个数
int[] buckets = new int[10];
//将数据出现的次数存储在buckets中
for (int value : arr) {
//(value / exp) % 10 :value的最底位(个位)
buckets[(value / exp) % 10]++;
}
//更改buckets[i],记录当前位置i的元素累计记数,方便对应到数组temp中的位置
for (int i = 1; i < 10; i++) {
buckets[i] += buckets[i - 1];
}
//从后向前,将数据存储到临时数组temp中
for (int i = arr.length - 1; i >= 0; i--) {
temp[buckets[(arr[i] / exp) % 10] - 1] = arr[i];
buckets[(arr[i] / exp) % 10]--;
}
//将有序元素temp赋给arr
System.arraycopy(temp, 0, arr, 0, arr.length);
}
}
}
方法二:
package com.zhx;
/*
* 另一种实现方式:
* 数组:[26, 3, 49, 556, 81, 9, 863, 0]
* 1、创建桶(下标0~9),并以个位数为下标,从第一个元素开始,依次放入桶中。
* 0[0]
* 1[81]
* 2[]
* 3[3,863]
* 4[]
* 5[]
* 6[26,556]
* 7[]
* 8[]
* 9[49,9]
* 遍历桶,将元素依次取出,完成第一次排序:[0, 81, 3, 863, 26, 556, 49, 9]
* 2、以十位数为下标,将完成第一次排序的数组从第一个元素开始,依次放入桶中。
* 0[0,3,9]
* 1[]
* 2[26]
* 3[]
* 4[49]
* 5[556]
* 6[863]
* 7[]
* 8[81]
* 9[]
* 遍历桶,将元素依次取出,完成第二次排序:[0, 3, 9, 26, 49, 556, 863, 81]
* 3、以百位数为下标,将完成第二次排序的数组从第一个元素开始,依次放入桶中。
* 0[0,3,9,26,49,81]
* 1[]
* 2[]
* 3[]
* 4[]
* 5[556]
* 6[]
* 7[]
* 8[863]
* 9[]
* 遍历桶,将元素依次取出,完成第三次排序:[0, 3, 9, 26, 49, 81, 556, 863]
*/
import java.util.ArrayList;
import java.util.Arrays;
public class Test {
private static void radixSort(int[] arr) {
//查找最大值,确定排序的次数
int max = arr[0];
for (int anArr : arr) {
if (anArr > max) {
max = anArr;
}
}
//从个位开始,对数组进行排序
for (int exp=1; max/exp>0; exp*=10) {
// 创建桶并初始化(桶的下标 0~9)
ArrayList<ArrayList<Integer>> buckets = new ArrayList<ArrayList<Integer>>();
for(int i=0;i<10;i++) {
buckets.add(i,new ArrayList());
}
// 将数据存储在buckets中
for (int value : arr) {
buckets.get((value/exp)%10).add(value);
}
//将每一次排序的结果复制到arr数组中
int k=0;
for(ArrayList<Integer> list : buckets) {
for(Integer num : list) {
arr[k++]=num;
}
}
//System.out.println(Arrays.toString(arr));
}
}
public static void main(String[] args) {
int[] arr = { 26, 3, 49, 556, 81, 9, 863, 0 };
radixSort(arr);
System.out.println(Arrays.toString(arr));
}
}