数据结构相关的内容在这里。
package sort;
import java.util.Arrays;
public class ArraySorter {
/**
* int数组的排序工具 复习五种排序方法: 交换排序 插入排序 选择排序 归并排序 分配排序
* 相应方法都是用来复习面试的,不讨论数据量和数据大小等问题
* 菜鸟收集整理之作
* @author Peter Zhang
*/
//private static int[] arr = { 5, 9, 8, 7, 2, 4, 1, 3, 0, 6 };//待测数组
private static int[] arr = {1234,5425,38,35,46,13,89,356,123,78963,51,62};
public static void main(String[] args) {
System.out.println("待测数组");
print(arr);
//Arrays.sort(arr);
bubbleSort(arr);
//bubbleSort2(arr);
// quickSort(arr);
// insertSort(arr);
// shellSort(arr);
// shellSort2(arr);
// selectSort(arr);
// heapSort(arr);
// mergeSort(arr);
//radixSort(arr);
//radixSort2(arr);
print(arr);
}
// 显示打印的方法
private static void print(int[] arr) {
for (int i : arr) {
System.out.print(i + " ");
}
System.out.println();
}
// 交换元素的方法
private static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
// 交换排序
/**
* 冒泡排序 数组中相邻左右两个元素相互比较,大的向后
*
* @param arr
*/
public static void bubbleSort2(int[] arr) {
for (int i = 0; i < arr.length; i++) {
for (int j = i + 1; j < arr.length - 1; j++) {
if (arr[i] > arr[j]) {
swap(arr, i, j);
}
}
}
}
public static void bubbleSort(int[] arr){
for(int i=0;i<arr.length;i++){
for(int j=arr.length-1;j>i;j--){
if(arr[j] <arr[j-1]){
swap(arr, j, j-1);
}
}
}
}
/**
* 快速排序 选出一个关键字,比他小的放到他的左边,大的放到右边, 设置两个指针,同时与关键字进行比较。
* 先确定中间位置的数(关键字)key一般都是第一个元素以及开始元素begin和结束元素end
* 再从右向左递减index,如果有元素比中间数小,就放在左边,和左边begin元素交换,begin+1
* 再从左向右递增index,如果有元素比中间数大,就放在右边,和右边的end元素交换,end+1 再递归左边和右边
*
* @param arr
* @param begin
* @param end
*/
private static void quick(int[] arr, int begin, int end) {
int i = begin;
int j = end;
if (i < j) {
int key = arr[i];
while (j > i) {
while (j > i && arr[j] > key) {// 右边递减寻找比关键字小的元素
j--;
}
if (j > i) {// 找到比关键字小的元素 下标为j
arr[i++] = arr[j]; // 和左边的元素交换 左边元素递增
}
while (j > i && arr[i] < key) {// 左边递增寻找比关键字大的元素
i++;
}
if (j > i) {// 找到比关键字大的元素 下标为i
arr[j--] = arr[i]; // 再右边递减寻找比关键字小的元素
}
}
arr[i] = key;
quick(arr, begin, j - 1);// 递归key左边
quick(arr, j + 1, end);// 递归key右边
}
}
// 外部方法
public static void quickSort(int[] arr) {
quick(arr, 0, arr.length - 1);
}
// 插入排序
/**
* 直接插入排序 左右分成两个部分,右边第一个元素和左边所有元素比较,小就交换,大就不变
*
* @param arr
*/
public static void insertSort(int[] arr) {
for (int i = 1; i < arr.length; i++) {
for (int j = 0; j < i; j++) {
if (arr[j] > arr[i]) {
swap(arr, i, j);
}
}
}
}
/**
* 希尔排序 先设定一个增量(间隔),再根据增量分组,每个分组排序;再分组,再排序
*
* @param arr
*/
public static void shellSort(int[] arr) {
int len = arr.length;
for (int increment = len / 2; increment > 0; increment /= 2) {// 分组
for (int i = increment; i < len; i++) {
if (arr[i] < arr[i - increment]) {// 增量间隔的两个数,大的放后,小的放前
for (int j = 0; j < i; j += increment) {
if (arr[j] > arr[i]) {
swap(arr, i, j);
}
}
}
}
}
}
public static void shellSort2(int[] arr) {
int len = arr.length;
int j;
for (int increment = len / 2; increment > 0; increment /= 2) {
for (int i = increment; i < len; i++) {
int temp = arr[i];
for (j = i - increment; j >= 0 && arr[j] > temp; j -= increment) {
arr[j + increment] = arr[j];
}
arr[j + increment] = temp;
}
}
}
// 选择排序
/**
* 直接选择排序 每次选择一个最小的
*
* @param arr
*/
public static void selectSort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
int min = i;
for (int j = i + 1; j < arr.length; j++) {
if (arr[min] > arr[j]) {
min = j;
}
}
if (min != i) {
swap(arr, i, min);
}
}
}
/**
* 堆排序 大顶堆排序 k0 k1 k2 k3 ……kn 利用大顶堆父节点比子节点大的原理,
* 先构造一个大顶堆,调整它保证根节点的元素是最大的
* 交换根节点和最后一个元素,移除最后一个元素,调整length-1个元素的堆,保持结构;
* 再交换此时的根节点和此时的最后一个元素,再移除此时的最后一个元素,调整剩下的堆;
* 以此类推,直到就剩根节点
*
* @param arr
*/
public static void heapSort(int[] arr) {
// 创建大顶堆堆 从最后一个父节点开始向根递减
int n = arr.length - 1; // 最后一个元素的index
for (int i = (n - 1) / 2; i > 0; i--) {
heapify(arr, i, n);// 从最后一个根节点开始调整堆
}
for (int i = n; i > 0; i--) {
swap(arr, i, 0);// 交换根和最后一个元素,n-1
heapify(arr, (i - 1 - 1) / 2, i - 1);// 从最后一个根节点开始调整
}
}
/**
* 调整堆 顶为0 左子节点为2i+1 从最后一个根节点开始调整堆的结构
*
* @param arr
* @param index 最后一个父节点
* @param n 最后一个元素的下标
*/
private static void heapify(int[] arr, int index, int n) {// n lastIndex
if (n == 0) {// 根节点 不调整
return;
}
for (int i = index; i >= 0; i--) {
int left = 2 * i + 1;// 左子节点
if (left < n) {// 有右子节点
if (arr[left] < arr[left + 1]) {
left++; // 方便在有右子节点的时候用left下标表示
}
}
if (arr[left] > arr[i]) {// 子节点比父节点大,交换
swap(arr, i, left);
}
}
}
// 归并排序
/**
* 归并排序 把待排序序列分为若干个子序列,每个子序列是有序的,
* 再把有序子序列合并为整体有序序列
*
* @param arr
*/
public static void mergeSort(int[] arr) {
merge(arr, 0, arr.length - 1);
}
// 分治法 自顶向下 递归分割数组并归并
private static void merge(int[] arr, int begin, int end) {
if (begin < end) {
int middle = (begin + end) / 2;
merge(arr, begin, middle);// 分割左边部分
merge(arr, middle + 1, end);// 分割右边部分
doMerge(arr, begin, middle, end);// 归并成一个有序的区间
}
}
// 归并
private static void doMerge(int[] arr, int begin, int middle, int end) {
int[] tmp = new int[arr.length];// 临时数组
int temp = begin;// 临时数组下标
int copy = begin;// 数组复制下标
int right = middle + 1;
while (begin <= middle && right <= end) {// 两部分从左边开始互相比较
if (arr[begin] <= arr[right]) {// 小的元素放入临时数组
tmp[temp++] = arr[begin++];
} else {
tmp[temp++] = arr[right++];
}
}
// 剩下的元素接着复制到临时数组中
while (begin <= middle) {
tmp[temp++] = arr[begin++];
}
while (right <= end) {
tmp[temp++] = arr[right++];
}
// 复制数组
while (copy <= end) {
arr[copy] = tmp[copy++];
}
}
// 分配排序
// 基数排序
/**
* int[] 单关键字十进制 基数就是10 循环装箱的次数就是数组中最大数的位数
* 用一个容量为 10*待测数组长度 的二维数组存放数据 new int[radix][arr.length]
* 即 10行 arr.length列的规则矩阵,每一行分别是序号为0-9的箱子
* 第一次循环装入个位数字与箱子序号数字对应的元素
* 再从0号箱子开始到9号箱子结束把依次所有元素装进数组中
* 第二次为十位
* 再从0号箱子开始到9号箱子结束把依次所有元素装进数组中
* 以此类推直到数组中最大数的最高位
* @param arr
*/
public static void radixSort(int[] arr) {
int len = arr.length;
int radix = 10;
int d = getMax(arr);// 最大数的位数
int[][] temp = new int[radix][len];//序号为0-9的箱子
int[] count = new int[radix];//箱子中元素的计数器
for (int m=0,n=1;m<d;m++,n *=radix) {//从个位到最大数的最高位
for (int i = 0; i < len; i++) {
int digit = (arr[i] / n % radix);//元素当前位的数值,对应箱子序号
temp[digit][count[digit]++] = arr[i];//把元素放入对应的箱子中
//count[digit]++; //对应序号箱子的计数器加1
}
int k=0; //数组下标,依次,
for (int i = 0; i < radix; i++) {
if (count[i] != 0){
for (int j = 0; j < count[i]; j++) {
arr[k] = temp[i][j];
k++;
}
}
count[i] = 0;
}
}
}
/**
* http://blog.csdn.net/skylinesky/article/details/6612119
* @author skylinesky
*/
public static void radixSort2(int[] array) {
int d = getMax(arr);
int radix = 10;
int[] temp = new int[arr.length];
int[] count = new int[radix];
int length = array.length;
int divide = 1;
for (int i = 0; i < d; i++) {
System.arraycopy(array, 0,temp, 0, length);
Arrays.fill(count, 0);
// for (int j = 0; j < array.length; j++) {
// temp[j] = arr[j];
// }
// for (int j = 0; j < count.length; j++) {
// count[j] = 0;
// }
for (int j = 0; j < length; j++) {
int tempKey = (temp[j] / divide) % radix;
count[tempKey]++;
}
for (int j = 1; j < radix; j++) {
count[j] = count[j] + count[j - 1];
}
// 个人觉的运用计数排序实现计数排序的重点在下面这个方法
for (int j = length - 1; j >= 0; j--) {
int tempKey = (temp[j] / divide) % radix;
count[tempKey]--;
array[count[tempKey]] = temp[j];
}
divide = divide * radix;
}
}
private static int getMax(int[] arr) {
int max = 0;
for (int i : arr) {
if (i > max) {
max = i;
}
}
return (max+"").length();
}
}