在看算法导论,把学习过程中的一些东西记录下来吧!
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++;
}
}
------------------------------------
学习 交流