最近在看《算法笔记》,如果单从算法来说,这本书真正做到了短小精悍,首先以排序入题,那么我们今天也来说说排序。
排序算法很多,我们按是否可以实现排序分为比较排序和非比较排序,在比较排序中常见的有,比较排序,梳排序,堆排序,归并排序,快递排序,内省排序等,非比较排序如,通排序,基数排序等。如果按传统的分类,则可以分为插入排序、折半插入排序、Shell排序、归并排序、直接选择排序、堆排序、冒泡排序、快速排序、桶式排序、基数排序等,各大排序基于不同的场景设置,各有优势。接下来就选取几个常见的说明。
BOOL CombSort(datatype *array, int size)
{
int i, j;
int increment;
if(array == NULL ) {
return FALSE;
}
increment = size;
while(TRUE) {
increment = (int)(increment / LAPSE_RATE);
for(i = 0; i < increment; i++) {
for(j = i+increment; j < size; j += increment) {
if(array[j] < array[j-increment]) {
Swap(array+j, array+j-increment);
}
}
}
if(increment <= 1) {
break;
}
}
return TRUE;
}
public class ArrayUtils {
public static void printArray(int[] array) {
System.out.print("{");
for (int i = 0; i < array.length; i++) {
System.out.print(array[i]);
if (i < array.length - 1) {
System.out.print(", ");
}
}
System.out.println("}");
}
public static void exchangeElements(int[] array, int index1, int index2) {
int temp = array[index1];
array[index1] = array[index2];
array[index2] = temp;
}
}
public class HeapSort {
public static void main(String[] args) {
int[] array = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3 };
System.out.println("Before heap:");
ArrayUtils.printArray(array);
heapSort(array);
System.out.println("After heap sort:");
ArrayUtils.printArray(array);
}
public static void heapSort(int[] array) {
if (array == null || array.length <= 1) {
return;
}
buildMaxHeap(array);
for (int i = array.length - 1; i >= 1; i--) {
ArrayUtils.exchangeElements(array, 0, i);
maxHeap(array, i, 0);
}
}
private static void buildMaxHeap(int[] array) {
if (array == null || array.length <= 1) {
return;
}
int half = array.length / 2;
for (int i = half; i >= 0; i--) {
maxHeap(array, array.length, i);
}
}
private static void maxHeap(int[] array, int heapSize, int index) {
int left = index * 2 + 1;
int right = index * 2 + 2;
int largest = index;
if (left < heapSize && array[left] > array[index]) {
largest = left;
}
if (right < heapSize && array[right] > array[largest]) {
largest = right;
}
if (index != largest) {
ArrayUtils.exchangeElements(array, index, largest);
maxHeap(array, heapSize, largest);
}
}
}
public class MergeSortTest {
public static void main(String[] args) {
int[] data = new int[] { 5, 3, 6, 2, 1, 9, 4, 8, 7 };
print(data);
mergeSort(data);
System.out.println("排序后的数组:");
print(data);
}
public static void mergeSort(int[] data) {
sort(data, 0, data.length - 1);
}
public static void sort(int[] data, int left, int right) {
if (left >= right)
return;
// 找出中间索引
int center = (left + right) / 2;
// 对左边数组进行递归
sort(data, left, center);
// 对右边数组进行递归
sort(data, center + 1, right);
// 合并
merge(data, left, center, right);
print(data);
}
/**
* 将两个数组进行归并,归并前面2个数组已有序,归并后依然有序
*
* @param data
* 数组对象
* @param left
* 左数组的第一个元素的索引
* @param center
* 左数组的最后一个元素的索引,center+1是右数组第一个元素的索引
* @param right
* 右数组最后一个元素的索引
*/
public static void merge(int[] data, int left, int center, int right) {
// 临时数组
int[] tmpArr = new int[data.length];
// 右数组第一个元素索引
int mid = center + 1;
// third 记录临时数组的索引
int third = left;
// 缓存左数组第一个元素的索引
int tmp = left;
while (left <= center && mid <= right) {
// 从两个数组中取出最小的放入临时数组
if (data[left] <= data[mid]) {
tmpArr[third++] = data[left++];
} else {
tmpArr[third++] = data[mid++];
}
}
// 剩余部分依次放入临时数组(实际上两个while只会执行其中一个)
while (mid <= right) {
tmpArr[third++] = data[mid++];
}
while (left <= center) {
tmpArr[third++] = data[left++];
}
// 将临时数组中的内容拷贝回原数组中
// (原left-right范围的内容被复制回原数组)
while (tmp <= right) {
data[tmp] = tmpArr[tmp++];
}
}
public static void print(int[] data) {
for (int i = 0; i < data.length; i++) {
System.out.print(data[i] + "\t");
}
System.out.println();
}
}
public class ArrayUtils {
public static void printArray(int[] array) {
System.out.print("{");
for (int i = 0; i < array.length; i++) {
System.out.print(array[i]);
if (i < array.length - 1) {
System.out.print(", ");
}
}
System.out.println("}");
}
public static void exchangeElements(int[] array, int index1, int index2) {
int temp = array[index1];
array[index1] = array[index2];
array[index2] = temp;
}
}
测试
public class QuickSort {
public static void main(String[] args) {
int[] array = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3 };
System.out.println("Before sort:");
ArrayUtils.printArray(array);
quickSort(array);
System.out.println("After sort:");
ArrayUtils.printArray(array);
}
public static void quickSort(int[] array) {
subQuickSort(array, 0, array.length - 1);
}
private static void subQuickSort(int[] array, int start, int end) {
if (array == null || (end - start + 1) < 2) {
return;
}
int part = partition(array, start, end);
if (part == start) {
subQuickSort(array, part + 1, end);
} else if (part == end) {
subQuickSort(array, start, part - 1);
} else {
subQuickSort(array, start, part - 1);
subQuickSort(array, part + 1, end);
}
}
private static int partition(int[] array, int start, int end) {
int value = array[end];
int index = start - 1;
for (int i = start; i < end; i++) {
if (array[i] < value) {
index++;
if (index != i) {
ArrayUtils.exchangeElements(array, index, i);
}
}
}
if ((index + 1) != end) {
ArrayUtils.exchangeElements(array, index + 1, end);
}
return index + 1;
}
}
public class InsertSortTest {
public static void insertSort(int[] array) {
if (array == null || array.length < 2) {
return;
}
for (int i = 1; i < array.length; i++) {
int currentValue = array[i];
int position = i;
for (int j = i - 1; j >= 0; j--) {
if (array[j] > currentValue) {
array[j + 1] = array[j];
position -= 1;
} else {
break;
}
}
array[position] = currentValue;
}
}
public static void main(String[] args) {
int[] array = { 3, -1, 0, -8, 2, 1 };
ArrayUtils.printArray(array);
insertSort(array);
ArrayUtils.printArray(array);
}
}
/**
* 内省排序升序
*/
public static int sort_neixing_asc(int[] array, int start, int end,
int level) {
// 先进行快速排序,当递归深度到达一定深度时,进行堆排序
// 改动快速排序代码,增加返回值为递归次数,当次数大于一定值时停止递归,开始调用堆排序进行排序
level++;
int length = end - start + 1;
if (length < 2)
return level;
else if (length == 2) {
if (array[start] > array[end]) {
int temp = array[end];
array[end] = array[start];
array[start] = temp;
}
return level;
} else {
// 得出最大值和最小值
int min = array[start], max = array[start];
for (int i = start; i < start + length; i++) {
if (array[i] < min)
min = array[i];
if (array[i] > max)
max = array[i];
}
// 找出合适的中间数(按中间值找,最好是像计数排序一样先统计比元素小的个数,然后按照个数确定哪个做中间数)
int absMid = (min + max) / 2;
int offset = Math.abs(array[start] - absMid);
int relativeMid = array[start];
int midIndex = start;
for (int i = start; i < start + length; i++)
if (Math.abs(array[i] - absMid) < offset) {
offset = Math.abs(array[i] - absMid);
relativeMid = array[i];
}
int[] newArray = new int[length];
for (int i = 0; i < newArray.length; i++)
newArray[i] = -1;
for (int i = start, startIndex = 0, endIndex = length - 1; i < start
+ length; i++) {
if (array[i] < relativeMid) {
newArray[startIndex] = array[i];
startIndex++;
} else if (array[i] > relativeMid) {
newArray[endIndex] = array[i];
endIndex--;
}
}
for (int i = 0; i < newArray.length; i++)
if (newArray[i] == -1)
newArray[i] = relativeMid;
for (int i = start, newIndex = 0; i < start + length; i++, newIndex++) {
array[i] = newArray[newIndex];
if (array[i] == relativeMid)
midIndex = i;
}
if (level < 10) {// 递归深度小于10时使用快速排序
sort_neixing_asc(array, start, midIndex - 1, level);
sort_neixing_asc(array, midIndex + 1, length - 1 + start, level);
} else {
// 递归深度大于10时使用堆排序
sort_dui_asc(array);
}
return level;
}
}
/**
* 内省排序降序
*/
public static int sort_neixing_dasc(int[] array, int start, int end,
int level) {
// 先进行快速排序,当递归深度到达一定深度时,进行堆排序
// 改动快速排序代码,增加返回值为递归次数,当次数大于一定值时停止递归,开始调用堆排序进行排序
level++;
int length = end - start + 1;
if (length < 2)
return level;
else if (length == 2) {
if (array[start] < array[end]) {
int temp = array[end];
array[end] = array[start];
array[start] = temp;
}
return level;
} else {
// 得出最大值和最小值
int min = array[start], max = array[start];
for (int i = start; i < start + length; i++) {
if (array[i] < min)
min = array[i];
if (array[i] > max)
max = array[i];
}
// 找出合适的中间数(按中间值找,最好是像计数排序一样先统计比元素小的个数,然后按照个数确定哪个做中间数)
int absMid = (min + max) / 2;
int offset = Math.abs(array[start] - absMid);
int relativeMid = array[start];
int midIndex = start;
for (int i = start; i < start + length; i++)
if (Math.abs(array[i] - absMid) < offset) {
offset = Math.abs(array[i] - absMid);
relativeMid = array[i];
}
int[] newArray = new int[length];
for (int i = 0; i < newArray.length; i++)
newArray[i] = -1;
for (int i = start, startIndex = 0, endIndex = length - 1; i < start
+ length; i++) {
if (array[i] > relativeMid) {
newArray[startIndex] = array[i];
startIndex++;
} else if (array[i] < relativeMid) {
newArray[endIndex] = array[i];
endIndex--;
}
}
for (int i = 0; i < newArray.length; i++)
if (newArray[i] == -1)
newArray[i] = relativeMid;
for (int i = start, newIndex = 0; i < start + length; i++, newIndex++) {
array[i] = newArray[newIndex];
if (array[i] == relativeMid)
midIndex = i;
}
if (level < 10) {// 递归深度小于10时使用快速排序
sort_neixing_dasc(array, start, midIndex - 1, level);
sort_neixing_dasc(array, midIndex + 1, length - 1 + start,
level);
} else {
// 递归深度大于10时使用堆排序
sort_dui_dasc(array);
}
return level;
}
}
public class BucketSort {
/**
* 桶排序算法,对arr进行桶排序,排序结果仍放在arr中
* @param arr
*/
static void bucketSort(double arr[]){
int n = arr.length;
ArrayList arrList[] = new ArrayList [n];
//把arr中的数均匀的的分布到[0,1)上,每个桶是一个list,存放落在此桶上的元素
for(int i =0;i1){
for(int i =1;i=0&&((Double)list.get(j)>(Double)list.get(j+1));j--)
list.set(j+1, list.get(j));
list.set(j+1, temp);
}
}
}
}
/**
* 测试.....
* 这里的测试数据是一个含n个元素的数组,且每个元素满足0<=arr[i]<1
*/
public static void main(String[] args) {
double arr[] = {0.78,0.17,0.39,0.26,0.72,0.94,0.21,0.12,0.23,0.68};
bucketSort(arr);
for(int i = 0;i