1.快速排序Quick sort
原理,通过一趟扫描将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列
/**
* 快速排序算法
*
* @param array
* 待排序数组
* @param low
* 数组待排序部分开始索引
* @param high
* 数组待排序部分结束索引
*/
@Override
public void fastSort(E[] array, int low, int high)
{
// TODO Auto-generated method stub
if (low >= high || array == null)
return;
E sentry = array[low];
int i = low, j = high;
while (i < j)
{
while (i < j && sentry.compareTo(array[j]) <= 0)
j--;
if (i != j)
{
E temp = array[i];
array[i] = array[j];
array[j] = temp;
}
while (i < j && sentry.compareTo(array[i]) >= 0)
i++;
if (i != j)
{
E temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
fastSort(array, low, i - 1);
fastSort(array, i + 1, high);
}
/**
* 快速排序算法
*
* @param array
* 待排序数组
*/
@Override
public void fastSort(E[] array)
{
// TODO Auto-generated method stub
if (array == null)
return;
fastSort(array, 0, array.length - 1);
}
2. 桶排序Bucket sort
桶排序是稳定的,桶排序是常见排序里最快的一种,但是同时也非常耗空间,基本上是最耗空间的一种排序算法
/**
* 桶排序算法:适用于类型为非负整数的数组,数组中不可以有重复元素
*
* @param array
* 待排序数组
*/
@Override
public void bucketSort(int[] array)
{
// TODO Auto-generated method stub
if (array == null)
return;
int maxE = 0;
for (int i = 0; i < array.length; i++)
{
if (array[i] < 0)
return;
if (array[i] > maxE)
maxE = array[i];
}
if (maxE == 0)
return;
int[] bucket = new int[maxE + 1];
for (int i = 0; i < array.length; i++)
{
bucket[array[i]]++;
}
for (int i = 0, k = 0; i < bucket.length && k < array.length; i++)
{
if (bucket[i] > 0)
{
array[k++] = i;
}
}
}
3. 鸽巢排序Pigeonhole sort
原理类似桶排序,数组的索引位置就表示值,该索引位置的值表示出现次数,如果全部为1次或0次那就是桶排序
/**
* 鸽笼排序算法:对桶排序的改进,适用于类型为非负整数的数组,可以有重复元素
*
* @param array
* 待排序数组
*/
@Override
public void pigeonHoleSort(int[] array)
{
// TODO Auto-generated method stub
if (array == null)
return;
int maxE = 0;
for (int i = 0; i < array.length; i++)
{
if (array[i] < 0)
return;
if (array[i] > maxE)
maxE = array[i];
}
if (maxE == 0)
return;
int[] pigeonHole = new int[maxE + 1];
for (int i = 0; i < array.length; i++)
{
pigeonHole[array[i]]++;
}
for (int i = 0, k = 0; i < pigeonHole.length && k < array.length; i++)
{
if (pigeonHole[i] > 0)
{
for (int j = 0; j < pigeonHole[i]; j++)
array[k++] = i;
}
}
}
4. 插入排序Insertion sort
插入排序就是每一步都将一个待排数据按其大小插入到已经排序的数据中的适当位置,直到全部插入完毕。
/**
* 插入排序算法
*
* @param array
* 待排序数组
*/
@Override
public void insertSort(E[] array)
{
// TODO Auto-generated method stub
if (array == null)
return;
for (int i = 1; i < array.length; i++)
{
E cur = array[i];
int j = i - 1;
for (; j >= 0; j--)
{
if (cur.compareTo(array[j]) < 0)
array[j + 1] = array[j];
else
break;
}
if (j + 1 != i)
array[j + 1] = cur;
}
}
5. 希尔排序Shell sort
希尔排序Shell Sort是基于插入排序的一种改进
/**
* 希尔排序算法:內部用插入排序算法
*
* @param array
* 待排序数组
*/
@Override
public void shellSort(E[] array)
{
// TODO Auto-generated method stub
if (array == null)
return;
int increment = (array.length + 1) / 2;
while (increment >= 1)
{
for (int i = 0; i + increment < array.length; i++)
{
for (int j = i + increment; j < array.length; j += increment)
{
E cur = array[j];
int k = j - increment;
for (; k >= i; k -= increment)
{
if (cur.compareTo(array[k]) < 0)
array[k + increment] = array[k];
else
break;
}
if (k + increment != j)
array[k + increment] = cur;
}
}
increment /= 2;
}
}
6. 冒泡排序Bubble sort
临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换
/**
* 冒泡排序算法
*
* @param array
* 待排序数组
*/
@Override
public void bubbleSort(E[] array)
{
// TODO Auto-generated method stub
if (array == null)
return;
boolean exchanged = true;
for (int i = 0; i < array.length - 1; i++)
{
exchanged = false;
for (int j = 0; j < array.length - i - 1; j++)
{
if (array[j].compareTo(array[j + 1]) > 0)
{
E temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
exchanged = true;
}
}
if (exchanged == false)
break;
}
}
7. 鸡尾酒排序Cocktail sort
鸡尾酒排序基于冒泡排序,双向循环
/**
* 鸡尾酒排序算法:鸡尾酒排序基于冒泡排序,双向循环
*
* @param array
* 待排序数组
*/
@Override
public void cocktailSort(E[] array)
{
// TODO Auto-generated method stub
if (array == null)
return;
boolean exchanged = true;
int ii = 0, jj = array.length - 1;
while (exchanged && ii < jj)
{
exchanged = false;
for (int i = ii; i < jj; i++)
{
if (array[i].compareTo(array[i + 1]) > 0)
{
E temp = array[i];
array[i] = array[i + 1];
array[i + 1] = temp;
exchanged = true;
}
}
jj--;
for (int j = jj; j > ii; j--)
{
if (array[j - 1].compareTo(array[j]) > 0)
{
E temp = array[j];
array[j] = array[j - 1];
array[j - 1] = temp;
exchanged = true;
}
}
ii++;
}
}
8. 梳排序Comb sort
梳排序还是基于冒泡排序,与冒泡不同的是,梳排序比较的是固定距离处的数的比较和交换,类似希尔那样
这个固定距离是待排数组长度除以1.3得到近似值,下次则以上次得到的近似值再除以1.3,直到距离小至3时,以1递减
/**
* 梳排序算法:梳排序还是基于冒泡排序,与冒泡不同的是,梳排序比较的是固定距离处的数的比较和交换,
* 类似希尔那样,这个固定距离是待排数组长度除以1.3得到近似值,下次则以上次得到的近似值再除以1.3,直到距离小至3时,以1递减
*
* @param array
* 待排序数组
*/
@Override
public void combSort(E[] array)
{
// TODO Auto-generated method stub
if (array == null)
return;
int increment = (int) (array.length / 1.3);
while (increment > 3)
{
for (int i = 0; i + increment < array.length; i++)
{
for (int j = i + increment; j < array.length; j += increment)
{
E cur = array[j];
int k = j - increment;
for (; k >= i; k -= increment)
{
if (cur.compareTo(array[k]) < 0)
array[k + increment] = array[k];
else
break;
}
if (k + increment != j)
array[k + increment] = cur;
}
}
increment = (int) (increment / 1.3);
}
increment = 3;
while (increment > 0)
{
for (int i = 0; i + increment < array.length; i++)
{
for (int j = i + increment; j < array.length; j += increment)
{
E cur = array[j];
int k = j - increment;
for (; k >= i; k -= increment)
{
if (cur.compareTo(array[k]) < 0)
array[k + increment] = array[k];
else
break;
}
if (k + increment != j)
array[k + increment] = cur;
}
}
increment--;
}
}
9. 选择排序Selection sort
直接从待排序数组里选择一个最小(或最大)的数字,每次都拿一个最小数字出来,顺序放入新数组,直到全部拿完
/**
* 简单选择排序算法
*
* @param array
* 待排序数组
*/
@Override
public void simpleSelectSort(E[] array)
{
// TODO Auto-generated method stub
if (array == null)
return;
boolean exchanged = true;
int min;
for (int i = 0; i < array.length - 1; i++)
{
exchanged = false;
min = i;
for (int j = i + 1; j < array.length; j++)
{
if (array[j].compareTo(array[min]) < 0)
{
// min = j;
E temp = array[min];
array[min] = array[j];
array[j] = temp;
exchanged = true;
}
}
// if (min != i)
// {
// E temp = array[min];
// array[min] = array[i];
// array[i] = temp;
// exchanged = true;
// }
if (exchanged == false)
break;
}
}
10. 归并排序Merge sort 把原始数组分成若干子数组,对每一个子数组进行排序,继续把子数组与子数组合并,合并后仍然有序,直到全部合并完,形成有序的数组
private void mergeSort(E[] array, int start, int mid, int end)
{
if (array == null)
return;
if (start <= mid && mid < end)
{
Object[] arrayTemp = new Object[mid - start + 1];
for (int i = 0; i < arrayTemp.length; i++)
arrayTemp[i] = array[start + i];
int i = start, j = mid + 1, k = start;
while (i <= mid && j <= end)
{
if (((E) arrayTemp[i - start]).compareTo(array[j]) > 0)
{
array[k++] = array[j++];
} else
{
array[k++] = (E) arrayTemp[i++ - start];
}
}
while (i <= mid)
array[k++] = (E) arrayTemp[i++ - start];
}
}
/**
* 归并排序算法
*
* @param array
* 待排序数组
* @param start
* 数组待排序部分开始索引
* @param end
* 数组待排序部分结束索引
*/
@Override
public void mergeSort(E[] array, int start, int end)
{
// TODO Auto-generated method stub
if (array == null)
return;
if (start < end)
{
int mid = (start + end) / 2;
mergeSort(array, start, mid);
mergeSort(array, mid + 1, end);
mergeSort(array, start, mid, end);
}
}
/**
* 归并排序算法
*
* @param array
* 待排序数组
*/
@Override
public void mergeSort(E[] array)
{
// TODO Auto-generated method stub
if (array == null)
return;
mergeSort(array, 0, array.length - 1);
}
11. 堆排序Heap sort
private void buildingHeap(Object[] heapArray)
{
if (heapArray == null)
return;
int heapLength = heapArray.length;
int startIndex = heapLength / 2;
while (startIndex > 0)
{
int startIndexTemp = startIndex;
while (startIndexTemp <= heapLength / 2)
{
int childIndex = startIndexTemp * 2 - 1;
if (startIndexTemp * 2 + 1 <= heapLength)
childIndex = (((E) heapArray[startIndexTemp * 2 - 1])
.compareTo((E) heapArray[startIndexTemp * 2]) < 0) ? startIndexTemp * 2 - 1
: startIndexTemp * 2;
if (((E) heapArray[startIndexTemp - 1])
.compareTo((E) heapArray[childIndex]) > 0)
{
Object temp = heapArray[startIndexTemp - 1];
heapArray[startIndexTemp - 1] = heapArray[childIndex];
heapArray[childIndex] = temp;
}
startIndexTemp = childIndex + 1;
}
startIndex--;
}
}
private void heapify(Object[] heapArray, int n)
{
if (heapArray == null || n <= 1)
return;
int heapLength = n;
for (int i = 1; i <= heapLength / 2;)
{
int childIndex = i * 2 - 1;
if (i * 2 + 1 <= heapLength)
childIndex = (((E) heapArray[i * 2 - 1])
.compareTo((E) heapArray[i * 2]) < 0) ? i * 2 - 1
: i * 2;
if (((E) heapArray[i - 1]).compareTo((E) heapArray[childIndex]) <= 0)
return;
Object temp = heapArray[i - 1];
heapArray[i - 1] = heapArray[childIndex];
heapArray[childIndex] = temp;
i = childIndex + 1;
}
}
/**
* 堆排序算法
*
* @param array
* 待排序数组
*/
@Override
public void heapSort(E[] array)
{
// TODO Auto-generated method stub
if (array == null)
return;
Object[] heapArray = new Object[array.length];
for (int i = 0; i < heapArray.length; i++)
heapArray[i] = array[i];
int heapLength = heapArray.length;
int arrayLength = 0;
buildingHeap(heapArray);
while (heapLength > 0)
{
array[arrayLength++] = (E) heapArray[0];
Object temp = heapArray[0];
heapArray[0] = heapArray[heapLength - 1];
heapArray[heapLength - 1] = temp;
heapLength--;
heapify(heapArray, heapLength);
}
}
12. 地精排序Gnome Sort
最简单的排序算法,只有一层循环,默认情况下前进冒泡,一旦遇到冒泡的情况发生就往回冒,直到把这个数字放好为止
/**
* 地精排序算法:最简单的排序算法,只有一层循环,默认情况下前进冒泡,一旦遇到冒泡的情况发生就往回冒,直到把这个数字放好为止
*
* @param array
* 待排序数组
*/
@Override
public void gnomeSort(E[] array)
{
// TODO Auto-generated method stub
if (array == null)
return;
int n = array.length;
int i = 0;
while (i < n)
{
if (i == 0 || array[i - 1].compareTo(array[i]) <= 0)
i++;
else
{
E temp = array[i];
array[i] = array[i - 1];
array[--i] = temp;
// i--;
}
}
}
13. 奇偶排序Odd-even sort
基本思路是奇数列与相邻的下一个偶数列比较交换排一趟序,偶数列与相邻的下一个奇数列比较交换排一趟序,交替进行,直到全部有序
/**
* 奇偶排序算法:基本思路是奇数列与相邻的下一个偶数列比较交换排一趟序,偶数列与相邻的下一个奇数列比较交换排一趟序,交替进行,直到全部有序
*
* @param array
* 待排序数组
*/
@Override
public void oddEvenSort(E[] array)
{
// TODO Auto-generated method stub
if (array == null)
return;
int odd = 0, even = 1;
boolean exchanged = true;
while (exchanged)
{
exchanged = false;
// 偶数列
for (int i = odd; i < array.length - 1; i += 2)
{
if (array[i].compareTo(array[i + 1]) > 0)
{
E temp = array[i];
array[i] = array[i + 1];
array[i + 1] = temp;
exchanged = true;
}
}
// 奇数列
for (int i = even; i < array.length - 1; i += 2)
{
if (array[i].compareTo(array[i + 1]) > 0)
{
E temp = array[i];
array[i] = array[i + 1];
array[i + 1] = temp;
exchanged = true;
}
}
}
}
14. 计数排序Counting sort
选票数组用来统计比当前数小的数的个数,有几个数就有几张选票,那么最小的数有0张,最大的数有数组长度减1张。
根据选票数进行入桶,入桶后的顺序即使排好序的顺序。
/**
* 计数排序算法:计数排序同时兼有桶排的高效和快排的霸道,时间复杂度O(n^2),空间复杂度O(n);小于等于桶排序的空间复杂度
*
* @param array
* 待排序数组
*/
@Override
public void countingSort(E[] array)
{
// TODO Auto-generated method stub
if (array == null)
return;
int[] ballot = new int[array.length];
Object[] bucket = new Object[array.length];
for (int i = 0; i < array.length - 1; i++)
{
for (int j = i + 1; j < array.length; j++)
{
// 拉选票
if (array[i].compareTo(array[j]) > 0)
ballot[i]++;
else
ballot[j]++;
}
}
for (int i = 0; i < array.length; i++)
{
bucket[ballot[i]] = array[i];
}
for (int i = 0; i < array.length; i++)
{
array[i] = (E) bucket[i];
}
}