今天随便翻了翻Java数据结构与算法这本书,写了一些常见的简单算法。当练习一下。当然代码不是十分完善,只是演示算法而已。
/** * 排序、查找算法 * @author sunlong * */ public class OrderArray { private int[] arr; private int length; public OrderArray(int size){ arr = new int[size]; length = 0; } /** * 未检查边界,有序插入 * @param value */ public void insert(int value){ int pos = length; for(int i=0; i<length; i++){ if(arr[i] > value){ pos = i; break; } } for(int j = length; j > pos; j--){ arr[j] = arr[j-1]; } arr[pos] = value; length++; } /** * 无序插入 * @param value */ public void insertNoOrder(int value){ arr[length++] = value; } /** * 二分查找 * @param value * @return */ public int find(int value){ int lower = 0, higher = length-1, current = (lower+higher)/2; while(lower <= higher){ if(arr[current] == value){ return current; }else if(arr[current] > value){ higher = current - 1; }else{ lower = current + 1; } current = (lower+higher)/2; } return -1; } public int find2(int value){ return findDiGui(0, length-1, value); } /** * 递归的二分查找 * @return */ public int findDiGui(int lower, int higher, int value){ int current = (lower+higher)/2; if(lower > higher) return -1; if(arr[current] == value){ return current; }else if(arr[current] > value){ higher = current - 1; }else{ lower = current + 1; } return findDiGui(lower, higher, value); } public void print(){ for(int i=0; i<length; i++) System.out.print(arr[i]+","); System.out.println(); } /** * 冒泡排序 * 比较相临的两个元素 */ public void bubbleSort(){ int tmp; for(int i=length-1; i>=0; i--){ for(int j=0; j<i; j++){ if(arr[j]>arr[j+1]){ tmp = arr[j+1]; arr[j+1] = arr[j]; arr[j] = tmp; } } } } /** * 选择排序改进了冒泡排序,使得交换次数从o(n*n)降到o(n) * 选择排序是第一遍扫描选择最小的值,然后和0位置交换,接着再选择次小的值和1位置交换,直到全部完成 */ public void selectSort(){ if(length == 0) return ; int min = 0, tmp; for(int j=0; j<length; j++){ for(int i=j+1; i<length; i++){ if(arr[min] > arr[i]){ min = i; } } tmp = arr[min]; arr[min] = arr[j]; arr[j] = tmp; } } /** * 插入排序,通常比冒泡和选择排序要好,虽然比较o(n*n) * 它以局部有序为前提 * 假设标记的左边全部有序,则要在左边插入这个标记的值。 */ public void insertSort(){ int tmp; for(int i=1; i<length; i++){ tmp = arr[i]; int j = i; while(j>0 && arr[j-1]>tmp){ arr[j] = arr[j-1]; j--; } arr[j] = tmp; } } /** * 归并排序o(n*logN),比冒泡、选择、插入排序要好 * 思想是归并两个已经有序的数组,把一个数组一分为二,再一分为二…… */ public void mergeSort(){ int[] workspace = new int[length]; recMerge(workspace, 0, length-1); } private void recMerge(int[] workspace, int lower, int higher){ if(lower == higher) return; else{ int mid = (lower + higher)/2; recMerge(workspace, lower, mid); recMerge(workspace, mid+1, higher); merge(workspace, lower, mid, higher); } } /** * 合并两个数组,分别是arr数组中的lower至mid,还有一个是mid+1至higher * 合到workspace中,然后把workspace中数据复制到lower至higher中 * @param workspace * @param lower * @param mid * @param higher */ private void merge(int[] workspace, int lower, int mid, int higher){ int left = lower; int right = mid+1; int index = 0; while(left<=mid && right<=higher){ if(arr[left] < arr[right]){ workspace[index++] = arr[left++]; }else{ workspace[index++] = arr[right++]; } } //有可能left部分的数组没有考完,但是right已经结束了,所以不需要再比较,直接把 //left部分剩余的数复制过去即可 while(left<=mid){ workspace[index++] = arr[left++]; } //同上分析 while(right<=higher){ workspace[index++] = arr[right++]; } int n = higher-lower+1; for(int i=0; i<n; i++){ arr[lower+i] = workspace[i]; } } /** * 希尔排序是对插入排序的一种改进,它使用n-增量法,首先对间隔n的数进行排序,然后逐渐减少间隔n直到变成1,此时 * 数组基本有序,那么再进行插入排序,将大大提高插入排序的效率 * 间隔算法可以用Knuth提出的算法,间隔以1开始,逆向使用。 * 算法为n=3*n+1,n初始为1,递归生成 * 比如1,然后n=3*1+1=4,然后n=3*4+1=13…… * * 举例来说10个数,h=4,则(0,4,8) (1,5,9) (2,6) (3,7) * 在排序时每组先比较前两个数,排完返回,再对第三个数处理,所以实际上是 * (0,4) (1,5) (2,6) (3,7) (0, 4, 8) (1, 5, 9) * 当然个人觉得可以按小组来排完再说,我的写法是基于此方式 */ public void shellSort(){ /*个人按理解写的希尔排序*/ int h = 1; while(h<=length/3){ h = h*3 + 1; } int tmp; while(h>0){ for(int span=0; span<h; span++){ for(int i=(h+span); i<length; i+=h){//每组进行插入排序 tmp = arr[i]; int index = i;//index用于向前遍历 while(index>=h && arr[index-h]> tmp){ arr[index] = arr[index-h];//向右移动数据 index -= h; } arr[index] = tmp; } } h = (h-1)/3; } /*以下是Java数据结构与算法中的写法 int inner, outer; int temp; int h = 1; while (h <= length/3){ h = h*3 + 1; } while (h > 0) { for (outer = h; outer < length; outer++) { temp = arr[outer]; inner = outer; while (inner > h - 1 && arr[inner - h] >= temp) { arr[inner] = arr[inner - h]; inner -= h; } arr[inner] = temp; } h = (h - 1) / 3; }*/ } }