数组高级应用—排序与查找
1、数组排序
1)冒泡排序
/** * 冒泡排序基本概念是: * 依次比较相邻的两个数,将小数放在前面,大数放在后面。 * 即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后。 * 然后比较第2个数和第3个数,将小数放前,大数放后,如此继续, * 直至比较最后两个数,将小数放前,大数放后。至此第一趟结束, * 将最大的数放到了最后。在第二趟:仍从第一对数开始比较 * (因为可能由于第2个数和第3个数的交换,使得第1个数不再小于第2个数), * 将小数放前,大数放后,一直比较到倒数第二个数(倒数第一的位置上已经是最大的), * 第二趟结束,在倒数第二的位置上得到一个新的最大数 * (其实在整个数列中是第二大的数)。如此下去,重复以上过程,直至最终完成排序。 */ class BubbleSort { public static void bubbleSort(int[] arr){ 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]){ SortTest.swap(arr,j,j+1); } } } } }
2)选择排序
/** * * 选择排序基本思路: * 把第一个元素依次和后面的所有元素进行比较。 * 第一次结束后,就会有最小值出现在最前面。 * 依次类推 */ public class SelectSort { public static void selectSort(int[] arr) { for (int i = 0; i < arr.length - 1; i++) { int minFlag = i; for (int j = i + 1; j < arr.length; j++) { if (arr[minFlag] > arr[j]) { minFlag = j; } } if (i != minFlag) { SortTest.swap(arr, i, minFlag); } } } }
3)插入排序
/** * * 插入排序基本思想 * 将n个元素的数列分为已有序和无序两个部分,如插入排序过程示例下所示: * {{a1},{a2,a3,a4,…,an}} * {{a1⑴,a2⑴},{a3⑴,a4⑴ …,an⑴}} * {{a1(n-1),a2(n-1) ,…},{an(n-1)}} * 每次处理就是将无序数列的第一个元素与有序数列的元素从后往前逐个进行比较, * 找出插入位置,将该元素插入到有序数列的合适位置中。 */ public class InsertSort { public static void insertSort(int[] arr) { for (int i = 1; i < arr.length; i++) { for (int j = i - 1; j >= 0; j--) { if(arr[j] > arr[j+1]){ SortTest.swap(arr,j,j+1); } } } } }
4)希尔排序
/** * * 希尔排序:先取一个小于n的整数d1作为第一个增量, * 把文件的全部记录分成(n除以d1)个组。所有距离为d1的倍数的记录放在同一个组中。 * 先在各组内进行直接插入排序;然后,取第二个增量d2<d1重复上述的分组和排序, * 直至所取的增量dt=1(dt<dt-l<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。 */ /** * 属于插入类排序,是将整个无序列分割成若干小的子序列分别进行插入排序 * 排序过程:先取一个正整数d1<n,把所有序号相隔d1的数组元素放一组, * 组内进行直接插入排序;然后取d2<d1,重复上述分组和排序操作;直至di=1, 即所有记录放进一个组中排序为止 * 初始:d=5 49 38 65 97 76 13 27 49 55 04 * 49 13 |--------------| * 38 27 |--------------| * 65 49 |--------------| * 97 55 |--------------| * 76 04 |--------------| * 一趟结果 13 27 49 55 04 49 38 65 97 76 * d=3 13 27 49 55 04 49 38 65 97 76 * 13 55 38 76 |---------|--------|--------| * 27 04 65 |---------|--------| * 49 49 97 |----------|--------| * 二趟结果 13 04 49* 38 27 49 55 65 97 76 * d=1 13 04 49 38 27 49 55 65 97 76 * |---|---|---|---|---|---|---|---|---| 三趟结果 * 04 13 27 38 49 49 55 65 76 97 */ public class ShellSort { public static void shellSort(int[] arr) { for (int i = arr.length / 2; i > 2; i = i / 2) { for (int j = 0; j < i; j++) { insertSort(arr, j, i); } } insertSort(arr, 0, 1); } public static void insertSort(int[] arr, int start, int inc) { for(int i = start+inc; i < arr.length;i+=inc){ for(int j = i-inc; j >= 0; j-=inc){ if(arr[j] > arr[j+inc]){ SortTest.swap(arr,j,j+inc); } } } } }
5)快速排序
/** * 快速排序: * 一趟快速排序的算法是: * 1)设置两个变量i、j,排序开始的时候:i=0,j=N-1; * 2)以第一个数组元素作为关键数据,赋值给key,即 key=A[0]; * 3)从j开始向前搜索,即由后开始向前搜索(j=j-1即j--), * 找到第一个小于key的值A[j],A[i]与A[j]交换; * 4)从i开始向后搜索,即由前开始向后搜索(i=i+1即i++), * 找到第一个大于key的A[i],A[i]与A[j]交换; * 5)重复第3、4、5步,直到 I=J; * (3,4步是在程序中没找到时候j=j-1,i=i+1,直至找到为止。 * 找到并交换的时候i, j指针位置不变。 * 另外当i=j这过程一定正好是i+或j-完成的最后令循环结束。) */ public class QuickSort { public static void quinckSort(int[] arr) { sort(arr, 0, arr.length - 1); } public static void sort(int[] arr, int i, int j) { int pivotIndex = partition(arr,i,j); if(i < j){ sort(arr,i,pivotIndex-1); sort(arr,pivotIndex+1,j); } } public static int partition(int[] array, int low, int high){ int pivokey = array[low]; while(low < high){ while(low < high && array[high] >= pivokey) { high--; } array[low] = array[high]; while(low < high && array[low] <= pivokey) { low++; } array[high] = array[low]; } array[low] = pivokey; return low; } }
6)归并排序
/** * * 归并操作(merge),也叫归并算法,指的是将两个已经排序的序列合并成一个序列的操作。 * 如设有数列{6,202,100,301,38,8,1} * 初始状态: [6] [202] [100] [301] [38] [8] [1] 比较次数 * i=1 [6 202 ] [ 100 301] [ 8 38] [ 1 ] 3 * i=2 [ 6 100 202 301 ] [ 1 8 38 ] 4 * i=3 [ 1 6 8 38 100 202 301 ] 4 */ public class MergeSort { public static void mergeSort(int[] arr){ sort(arr,0,arr.length-1); } public static 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); } } 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++]; } // 把新数组中的数覆盖nums数组 for (int k2 = 0; k2 < temp.length; k2++) { arr[k2 + low] = temp[k2]; } } }
7)堆排序
public class HeapSort { public static void heapSort(int[] arr) { buildHeap(arr); // 建立堆 int i = 0; for (i = arr.length - 1; i >= 1; i--) { SortTest.swap(arr, 0, i); heapify(arr, 0, i); } } public static void buildHeap(int[] arr) { int n = arr.length; for (int i = n / 2 - 1; i >= 0; i--) { heapify(arr, i, n); } } public static void heapify(int[] arr, int idx, int max) { int left = 2 * idx + 1; int rigth = 2 * idx + 2; int largest = 0; if (left < max && arr[left] > arr[idx]) largest = left; else largest = idx; if (rigth < max && arr[rigth] > arr[largest]) largest = rigth; if (largest != idx) { SortTest.swap(arr, largest, idx); heapify(arr, largest, max); } } }
2、数组二分查找
public class BinarySearch { public static void main(String[] args) { int[] arr = {11, 22, 33, 44, 55, 66, 77, 88, 99}; int index = binarySearch(arr, 88); System.out.println("index:" + index); index = binarySearch(arr, 100); System.out.println("index:" + index); } public static int binarySearch(int[] arr, int value) { int low = 0; int high = arr.length - 1; int mid = -1; while (low < high) { mid = (low + high) / 2; if (arr[mid] == value){ return mid; } if (value > arr[mid]) low = mid + 1; else high = mid - 1; } return -1; } }