各种排序

在看算法导论,把学习过程中的一些东西记录下来吧!


1)选择排序

/**
 *Apr 18, 2013
 *Copyright(c)JackWang
 *All rights reserve
 *@Author <a href="mailto:wangchengjack@163.com">JackWang</a>
 */
package com.example.sort;

/**
 * 选择排序 
 * 每次选择数组中最小的元素放在排序的位置,遍历之后即排好了序
 * 
 * @author Administrator
 * 
 */

public class Selection_Sort {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		int[] a = { 41, 4, 78, 5, 14, 56, 4, 74, 120, 103, 51 };
		a = Select_Sort(a);
		for (int i : a) {
			System.out.print(i + " ");
		}

	}

	public static int[] Select_Sort(int[] a) {
		for (int i = 0; i < a.length; i++) {
			int k = i;   //记录最小元素脚标,每趟找出最小脚标后交换位置
			for (int j = i + 1; j < a.length; j++) {
				if (a[k] > a[j]) {
					k = j;
				}

			}
			if (k != i) {
				int temp = a[i];
				a[i] = a[k];
				a[k] = temp;
			}
		}
		return a;
	}

}

2)插入排序

/**
 *Apr 18, 2013
 *Copyright(c)JackWang
 *All rights reserve
 *@Author <a href="mailto:wangchengjack@163.com">JackWang</a>
*/
package com.example.sort;
/**
 * 插入排序
 * 遍历要排序的数组,每一次把一个元素插入到已经排
 * 好序的子数组中,遍历到最后一个元素时即把整个数
 * 组排好了序
 * 时间开销 O(n^2)
 * 空间开销O(n)
 * 稳定的
 * @author Administrator
 *
 */

public class Insertion_Sort {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		int[] a = {41,4,78,5,14,56,4,74,120,103,51};
		a = Insert_Sort(a);
		for (int i : a) {
			System.out.print(i+" ");
		}

	}

	public static int[] Insert_Sort(int[] a) {
		/*
		 *每次要排序的元素为key[i]
		 *a[0] 默认情况下已经排好序 
		 */
		for(int i = 1;i<a.length;i++){
			for(int j = 0;j<i;j++){
				if (a[i]<a[j]) {
					int temp = a[j];
					a[j] = a[i];
					a[i] = temp;
				}
			}
		}
		return a;
	}

}


3)合并排序

/**
 *Apr 18, 2013
 *Copyright(c)JackWang
 *All rights reserve
 *@Author <a href="mailto:wangchengjack@163.com">JackWang</a>
 */
package com.example.sort;

/**
 * 合并排序 
 * 分治思想
 * Merge_Sort 可以对数组的任意部分进行合并排序
 * Merge_Sort1 只能对整个数组进行排序
 * 时间开销 O(nlgn)
 * 空间开销 O(n)
 * @author Administrator
 * 
 */

public class Mergtion_Sort {
	private static int[] a = { 41, 4, 78, 5, 14,45,6,12,56,13,85,68 };
	/**
	 * @param args
	 */
	public static void main(String[] args) {
//		Merge_Sort(a, 0, a.length-1);
		Merge_Sort1(a);
		for (int i : a) {
			System.out.print(i + " ");
		}
	}

	public static int[] Merge_Sort1(int[] a2) {
		if (a2.length > 1) {
			int mid = a2.length / 2;
			int[] leftArr = new int[mid];
			int[] rightArr = new int[a2.length - mid];
			for (int i = 0; i < leftArr.length; i++)
				leftArr[i] = a2[i];
			for (int j = 0; j < rightArr.length; j++)
				rightArr[j] = a2[mid + j];
			leftArr = Merge_Sort1(leftArr);
			rightArr = Merge_Sort1(rightArr);

			// 合并,考虑到脚标、数组的共享问题,最好把合并写到里面
			int i = 0;
			int j = 0;
			for (int k = 0; k < a2.length; k++) {
				if (i < leftArr.length && j < rightArr.length) {
					if (leftArr[i] < rightArr[j]) {
						a2[k] = leftArr[i];
						i++;
					} else {
						a2[k] = rightArr[j];
						j++;
					}
				} else if (i == leftArr.length && j < rightArr.length) {
					a2[k] = rightArr[j];
					j++;
				} else if (j == rightArr.length && i < leftArr.length) {
					a2[k] = leftArr[i];
					i++;
				}
			}

		}
		return a2;
	}

	public static void Merge_Sort(int[] a, int start, int end) {
		if ((end-start+1)> 1) {
			int mid = (end+start)/2;
			Merge_Sort(a, start, mid);
			Merge_Sort(a, mid+1, end);
			Merge(a,start,mid,end);
		} else {
			return;
		}
	}

	public static void Merge(int[] a, int start, int mid, int end) {
		int[] LeftArr = new int[mid-start+2];
		int[] RightArr = new int[end-mid+1];
		for (int i = 0; i < mid-start+1; i++)
			LeftArr[i] = a[start+i];
		LeftArr[mid-start+1] = Integer.MAX_VALUE;
		for (int j = 0; j < end-mid; j++)
			RightArr[j] = a[mid+1+j];
		RightArr[end-mid] = Integer.MAX_VALUE;
		int i = 0;
		int j = 0;
		int k = start;
		while (k < end+1) {
			if (LeftArr[i] < RightArr[j]) {
				a[k++] = LeftArr[i++];
			} else {
				a[k++] = RightArr[j++];
			}
		}
	}
}

本排序参考了该文章,在此表示感谢!

4)堆排序

/**
 *Apr 21, 2013
 *Copyright(c)JackWang
 *All rights reserve
 *@Author <a href="mailto:wangchengjack@163.com">JackWang</a>
*/
package com.example.sort;



public class HeapSort {
	private static int[] arr = {13, 27, 17, 3, 16, 13, 10, 1, 5, 7, 12, 4, 8, 9, 0 };
	public static void main(String[] args) {
		arr = heapSort(arr);
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i] + " ");
		}
	}
	public static int[] heapSort(int[] arr2) {
		arr2 = BuildHeap(arr2);
		int length = arr2.length;
		for(int i = arr2.length - 1; i>0;i--){
			int temp = arr2[i];
			arr2[i] = arr2[0];
			arr2[0] = temp;
			length--;
			MaxHeap(arr2, 0,length);
		}
		return arr2;
	}
	public static int[] BuildHeap(int[] arr2) {
		int i = arr2.length/2;
		while(i>=0){
			MaxHeap(arr2,i,arr2.length);
			i--;
		}
		return arr2;
	}
	public static void MaxHeap(int[] arr2, int i ,int length) {
		int left = i == 0 ?1 :2*i;
		int right = left+1;
		int largest = i;
		if (left < length && arr2[left] > arr2[i]) {
			largest = left;
		}
		if (right < length && arr2[right] > arr2[largest]) {
			largest = right;
		}
		if (largest != i) {
			int temp = arr2[largest];
			arr[largest] = arr2[i];
			arr2[i] = temp;
			MaxHeap(arr2,largest,length);
		}
		
	}

}


5)快速排序

/**
 *Apr 22, 2013
 *Copyright(c)JackWang
 *All rights reserve
 *@Author <a href="mailto:wangchengjack@163.com">JackWang</a>
 */
package com.example.sort;

import java.util.Random;

public class QuickSortDemo {
	private static int[] arr = { 13, 27, 17, 3, 16, 10, 1,13, 5, 7, 12, 4, 8, 9, 0 };

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		arr = QuickSort(arr, 0, arr.length - 1);
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i] + " ");
		}

	}

	public static int[] QuickSort(int[] arr2, int start, int end) {
		if (start < end) {
			// int CenterAixIndex = Partion(arr2,start,end);
			// int CenterAixIndex = RandomPartion1(arr2, start, end);
			int CenterAixIndex = RandomPartion2(arr2, start, end);
			QuickSort(arr2, start, CenterAixIndex - 1);
			QuickSort(arr2, CenterAixIndex + 1, end);
		}
		return arr2;
	}

	public static int RandomPartion2(int[] arr2, int start, int end) {
		int i = start - 1; // 表示比中轴小的部分的最后一个元素的脚标
		int random = new Random().nextInt(50) % (end - start + 1) + start;
		swap(arr2, random, end);    //将随机产生的脚标与最后一个元素互换,其他操作同Partion
		int p = arr2[end]; // 中轴
		for (int j = start; j < end; j++) {
			if (arr2[j] <= p) {
				i++;
				swap(arr2, i, j);
			}
		}
		swap(arr2, i + 1, end); // 把中轴作为大小部分数组的分界点
		return i + 1; // 返回分界点
	}

	/*
	 * 不能含有相同的元素的中轴,否则会陷入死循环 比如恰好中轴元素等于13,而数组总还有另外一个也等于13 则会陷入死循环
	 */
	public static int RandomPartion1(int[] arr2, int start, int end) {
		int i = start; // 从头开始
		int j = end; // 从尾开始
		int random = new Random().nextInt(50) % (end - start + 1) + start;
		int p = arr2[random]; // 中轴随机产生
		while (true) {
			while (arr2[i++] < p)
				;
			--i;
			while (arr2[j--] > p)
				;
			++j;
			if (j == i) {
				return i;
			} else if (i < j) {
				swap(arr2, i, j);
			}
		}

	}

	public static int Partion(int[] arr2, int start, int end) {
		int i = start - 1; // 表示比中轴小的部分的最后一个元素的脚标
		int p = arr2[end]; // 中轴
		for (int j = start; j < end; j++) {
			if (arr2[j] <= p) {
				i++;
				swap(arr2, i, j);
			}
		}
		swap(arr2, i + 1, end); // 把中轴作为大小部分数组的分界点
		return i + 1; // 返回分界点
	}

	private static void swap(int[] arr2, int i, int j) {
		int temp = arr2[i];
		arr2[i] = arr2[j];
		arr2[j] = temp;
	}
}

6)Stooge排序  

时间性能比插入排序还差。。。

/**
 *Apr 24, 2013
 *Copyright(c)JackWang
 *All rights reserve
 *@Author <a href="mailto:wangchengjack@163.com">JackWang</a>
*/
package com.example.sort;

public class StoogeSort {
	private static int[] arr = { 13, 27, 17, 3, 16, 10, 1,13, 5, 7, 12, 4, 8, 9, 0 };
//	private static int[] arr = { 13, 9, 21, 3 };

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		stoogeSort(arr,0,arr.length-1);
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i] + " ");
		}

	}

	public static void stoogeSort(int[] arr2, int i, int j) {
		if (arr2[i] > arr2[j])
			swap(arr2,i,j);
		if(i+1 < j){
			int k = (j-i+1)/3;
			stoogeSort(arr2, i, j-k);  //数组的前三分之二
			stoogeSort(arr2, i+k, j);  //数组的后三分之二
			stoogeSort(arr2, i, j-2*k);  //数组的前三分之二
		}else
			return;
	}
	
	private static void swap(int[] arr2, int i, int j) {
		int temp = arr2[i];
		arr2[i] = arr2[j];
		arr2[j] = temp;
	}

}

7)计数排序

/**
 *Apr 26, 2013
 *Copyright(c)JackWang
 *All rights reserve
 *@Author <a href="mailto:wangchengjack@163.com">JackWang</a>
*/
package com.example.sort;
/**
 * 计数排序
 * 优点:排序稳定,在n较大时时间复杂度远远低于比较排序O(n)
 * 缺点:空间复杂度较大
 * 		当元素值分布非常离散时空间复杂度就更大,极大浪费内存
 * @author Administrator
 *
 */

public class CountSort {
	private static int[] arr = {13, 27, 17, 3, 16, 13, 10, 1, 5, 7, 12, 4, 8, 9, 0 };
	private static int[] B = new int[arr.length]; //用于存储排序后的数组

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		arr = countSort(arr,27);
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i] + " ");
		}

	}

	/**
	 * 计数排序
	 * @param arr2 要排序的数组
	 * @param i   要排序数组中元素最大值
	 * @return
	 */
	public static int[] countSort(int[] arr, int k) {
//		int[] B = new int[arr.length];    
		int[] C = new int[k+1];           //记录每个元素的位置
		/*
		 * 初始化C数组
		 */
		for(int i = 0;i<=k;i++)
			C[i] = 0;
		for(int i = 0;i<arr.length;i++)
			C[arr[i]] = C[arr[i]] + 1;
		for(int i = 1;i<C.length;i++)
			C[i] += C[i - 1];
		for(int i = arr.length-1;i>=0;i--){
			B[C[arr[i]]-1] = arr[i];
			C[arr[i]] = C[arr[i]] - 1;
		}
		return B;
	}

}


附:习题:逆序对

/**
 *Apr 19, 2013
 *Copyright(c)JackWang
 *All rights reserve
 *@Author <a href="mailto:wangchengjack@163.com">JackWang</a>
 */
package com.example.sort;

/**
 * 计算逆序对(i<j 当A[i]>A[j]就是一个逆序对) 1)改造合并排序 2)改造冒泡排序
 * 
 * @author Administrator
 * 
 */

public class CountingInversion {
	private static int[] a = {41,4,78,5,14,56,4,74,120,103,51};
	private static int count = 0;

	/**
	 * @param args
	 */
	public static void main(String[] args) {
//		CountInversion(a, 0, a.length - 1);
		CountInversion1(a, 0, a.length - 1);
		System.out.println(count);

	}

	public static void CountInversion1(int[] a2, int start, int end) {
		for (int i = start; i < end; i++) {
			for (int j = i + 1; j < end + 1; j++) {
				if (a2[i] > a2[j])
					count++;
			}
		}
	}

	public static void CountInversion(int[] a2, int start, int end) {
		if ((end - start + 1) > 1) {
			int mid = (end + start) / 2;
			CountInversion(a, start, mid);
			CountInversion(a, mid + 1, end);
			Count(a, start, mid, end);
		} else {
			return;
		}
	}

	public static void Count(int[] a, int start, int mid, int end) {
		int[] LeftArr = new int[mid - start + 1];
		int[] RightArr = new int[end - mid];
		for (int i = 0; i < mid - start + 1; i++)
			LeftArr[i] = a[start + i];
		for (int j = 0; j < end - mid; j++)
			RightArr[j] = a[mid + 1 + j];
		for (int i = 0; i < LeftArr.length; i++)
			for (int j = 0; j < RightArr.length; j++)
				if (LeftArr[i] > RightArr[j])
					count++;
	}

}


------------------------------------

学习   交流

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值