Java几种排序小练习

今天随便翻了翻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;
		}*/
	}
}
 

你可能感兴趣的:(java,数据结构,算法,J#)