- 递归二分查找
- 冒泡排序
- 选择排序
- 插入排序
- 归并排序
- 快速排序
1、递归二分查找
思想:
使用二分查找的前提条件是数组元素必须已经排好序。
代码:
public static int binarySearch(int[] list, int key){ return binarySearch(list, key, 0, list.length - 1); } public static int binarySearch(int[] list, int key , int low, int high){ //没有查找到 if(low > high) return - low - 1; int mid = (low + high) / 2; if(key < list[mid]){ return binarySearch(list, key, low, mid - 1); }else if(key == list[mid]){ return mid; }else{ return binarySearch(list, key, mid + 1, high); } }
2、冒泡排序
动画演示:http://liveexample.pearsoncmg.com/dsanimation/BubbleSortNeweBook.html
思路:
依次比较相邻的两个数,将小数放在前面,大数放在后面。
即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后。然后比较第2个数和第3个数,将小数放前,大数放后,如此继续……直至比较最后两个数,将小数放前,大数放后。重复第一趟步骤,直至全部排序完成。
第一趟比较完成后,最后一个数一定是数组中最大的一个数,所以第二趟比较的时候最后一个数不参与比较;
第二趟比较完成后,倒数第二个数也一定是数组中第二大的数,所以第三趟比较的时候最后两个数不参与比较;
依次类推,每一趟比较次数-1;
……
代码:
public static void bubbleSort(int[] array) { // 优化:如果在某次遍历中没有发生交换,那么就不用再进行下一次遍历了,因为所有元素已经排好序了 boolean needNextPass = true; //需要array.length-1次遍历 for(int k = 1; k < array.length && needNextPass; k++){ needNextPass = false; //假设不需要进行下次遍历 //第k次遍历处理前array.length-k个数 for(int i = 0; i < array.length - 1; i++){ //依次比较相邻两个元素 if(array[i] > array[i + 1]){ //交换 int temp = array[i]; array[i] = array[i + 1]; array[i + 1] = temp; needNextPass = true; //需要进行下次遍历 } } } }
3、选择排序
动画演示:http://liveexample.pearsoncmg.com/dsanimation/SelectionSortNeweBook.html
思路:
找数组中最小的数,并将其和第一个数交换;
然后从剩下的数中找最小的数,和第二个交换;
……一直进行下去,直到仅剩一个数 (是一个递归的过程)
代码:
//主程序初始时候执行 selectionSort(array,0, array.length - 1) public static void selectionSort(double[] array, int low, int high){ if(low < high){ int indexOfMin = low; //最小数下标 double min = array[low]; //最小数 //找到最小的数min和最小数下标indexOfMin for(int i = low + 1; i <= high; i++){ if(array[i] < min){ min = array[i]; indexOfMin = i; } } //交换第low个元素与min array[indexOfMin] = array[low]; array[low] = min; //递归 selectionSort(array, low + 1, high); } }
4、插入排序
动画演示:http://liveexample.pearsoncmg.com/dsanimation/InsertionSortNeweBook.html
思路:
重复的将新的元素插入一个排好序的子线性表中,直到整个线性表排好序。
[0,1,4,6,3]
我们要做的从a[1]开始,至于为什么不是a[0]。a[0]之前没有与a[0]进行比较的元素。我们插入a[1],这个时候我们需要遍历a[1]和a[1]之前的所有元素并进行比较。设置一个变量j,用来记录第一个 比 a[1]元素小的那个元素的下标,也就是a[1]要插入的位置,这个时候跳出循环,并且没发现一个比a[1]大的元素,就要令这个元素后移一位。依次类推的算法直到整个数组的最后一个。
代码:
public static void insertionSortt(int[] array){ //从a[1]开始 for(int i = 1; i < array.length; i++){ int currentElement = array[i]; int j; //标记元素要移动到的位置 //先判断currentElement前面一个数,如果要移动,移动后再判断前面一个数,直到判断到不需要移动或已经判断到list[0] for(j = i - 1; j >=0 && array[j] > currentElement; j--){ //将currentElement前面一个数向后移动一位 array[j + 1] = array[j]; } array[j + 1] = currentElement; } }
5、归并排序
动画演示:http://liveexample.pearsoncmg.com/dsanimation/MergeSortNeweBook.html
思想:
使用分而治之法对数组排序。将数组分为两半,对每部分递归地应用归并排序。在两部分都排好序后,对它们进行归并。
代码:
public static void mergeSort(int[] array) { if (array.length > 1) { // 创建临时数组firstHalf存放前面一半的元素 int[] firstHalf = new int[array.length / 2]; System.arraycopy(list, 0, firstHalf, 0, array.length / 2); // 递归 mergeSort(firstHalf); // 创建临时数组secondHalf存放后面一半的元素 int lengthOfSecondHalf = array.length - array.length / 2; int[] secondHalf = new int[lengthOfSecondHalf]; System.arraycopy(array, array.length / 2, secondHalf, 0, lengthOfSecondHalf); // 递归 mergeSort(secondHalf); // 归并到原始数组array中 merge(firstHalf, secondHalf, array); } } /** 归并 */ public static void merge(int[] array1, int[] array2, int[] temp) { /* * 归并两个有序数组array1、array2为一个临时数组temp。 * current1和current2指向array1和array2中要考虑的当前元素,重复比较array1和array2中的当前元素,并将较小的一个元素移动到temp中。 * 如果较小元素在array1中,current1增加1;如果较小元素在array2中,current2增加1。 * 最后array1或array2会剩余一个元素没有移动,将它直接复制到temp中。 */ int current1 = 0;// array1中要考虑的当前元素 int current2 = 0;// array2中要考虑的当前元素 int current3 = 0;// temp中要考虑的当前元素 while (current1 < array1.length && current2 < array2.length) { // 如果较小元素在array1中,current1增加1 if (array1[current1] < array2[current2]) temp[current3++] = array1[current1++]; // 如果较小元素在array2中,current2增加1 else temp[current3++] = array2[current2++]; } while (current1 < array1.length) temp[current3++] = array1[current1++]; while (current2 < array2.length) temp[current3++] = array2[current2++]; }
6、快速排序
动画演示:http://liveexample.pearsoncmg.com/dsanimation/QuickSortNeweBook.html
思想:
在数组中选择一个基准元素(pivot),将数组分为两部分,使得第一部分中的所有元素都小于等于pivot,第二部分的所有元素都大于pivot。
对第一部分递归的应用快速排序算法,然后对第二部分递归的应用快速排序算法。
代码:
//主程序输入quickSort(array, 0, array.length - 1);开始执行 public static void quickSort(int[] array, int first, int last) { if(last > first){ //将基准元素放置到正确的位置,获得基准元素下标 int pivotIndex = partition(array, first, last); quickSort(array, 0, pivotIndex - 1); quickSort(array, pivotIndex + 1, last); } } /**将基准元素放置到正确的位置后返回基准元素下标*/ public static int partition(int[] array, int first, int last) { //将数组第一个元素作为基准元素 int pivot = array[first]; //初始情况下,low指向子数组中第二个元素 int low = first + 1; //初始情况下,high指向子数组中最后一个元素 int high = last; while(high > low) { //从左侧开始查找第一个大于基准元素的元素,如果array[low] <= pivot,跳过,继续找下一个,即low++ while(low <= high && array[low] <= pivot) { low++; } //从右侧开始查找第一个小于等于基准元素的元素,如果array[high] > pivot,跳过,继续找下一个,即high-- while(low <= high && array[high] > pivot) { high--; } //找到后交换 if(high > low){ int temp = array[low]; array[low] = list[high]; array[high] = temp; } } //low<high时,查找结束,从右开始寻找第一个小于等于pivot,即小于等于list[first]的元素,找到后与基准元素交换 while(high > first && array[high] > pivot){ high--; } if(pivot > array[high]){ array[first] = array[high]; array[high] = pivot; return high; }else{ return first; } }