快速排序
据说第一个正确的快排算法程序是在快排思想提出后的两三年才有人写出来,我们都是站在巨人的肩上码代码啊。
算法:
一趟排序为,选出一个哨兵元素,可以为左边第一个,然后从序列的最左边开始遍历,选出比哨兵元素小的元素下标,标记为r,从序列的左边开始遍历,选出比哨兵元素大的元素下边,标记为l,然后r、l下边的元素对换,然后重复上述遍历对换的操作,直至l下标不再下与r下标。将哨兵元素跟l元素对换。这样为一趟,就将哨兵元素的左边与右边分成两个子序列,左边子序列所有元素都比哨兵元素小,右边子序列所有元素都比哨兵元素大。然后分别对左右子序列进行快排。
public void quickSort(int array[], int low, int high) {
if (low >= high) {
return;
}
int sentinel = array[low];
int left = low;
int right = high;
while (left < right) {
while (left < right && array[right] >= sentinel) {
right --;
}
while(left < right && array[left] <= sentinel) {
left ++;
}
int temp = array[left];
array[left] = array[right];
array[right] = temp;
}
int temp = array[low];
array[low] = array[left];
array[left] = temp;
quickSort(array, low, left - 1);
quickSort(array, left + 1, high);
}
冒泡排序
思想:一趟冒泡排序为,从第一个元素开始遍历,通过每一个元素跟后面一个元素的比较,较大者在后面,则一趟排序下来,序列中最大的元素在最后一位,n-1趟冒泡后,则数组有序。
public static void popSort(int array[]) {
int unPopIndex = array.length - 1;
while(unPopIndex > 0) {
int popIndex = 0;
for (int i =0; i < unPopIndex; i ++) {
if (array[i] > array[i + 1]) {
int temp = array[i];
array[i] = array[i + 1];
array[i + 1] = temp;
popIndex = i;
}
}
unPopIndex = popIndex;
}
}
归并排序
思想:将原序列按照二分分成两个子串,对子串进行归并排序后,将两个子串合并。
public void mergeSort(int array[], int left, int right) {
if (right == left) {
return;
}
int mid = (right - left) / 2 + left;
mergeSort(array, left, mid);
mergeSort(array, mid + 1, right);
int temp[] = new int[right - left + 1];
int a = left;
int b = mid + 1;
int count = 0;
while(a <= mid && b <= right) {
temp[count ++] = array[a] < array[b] ? array[a ++] : array[b ++];
}
while(a <= mid) {
temp[count ++] = array[a ++];
}
while (b <= right) {
temp[count ++] = array[b ++];
}
for (int i = 0; i < right - left + 1; i ++ ) {
array[left + i] = temp[i];
}
}
堆排序
思想:最大(小)堆保证堆顶元素是队列中的最大(小)值,通过取堆顶元素,再调整剩下元素的堆状态,就可以获得排序后的数组。
//最小堆排序算法,先利用原数组建立一个堆,也就是通过对非叶子节点的“下潜操作”(与子节点对比,如果子节点较小,则交换),建立起一个堆,能保证堆顶元素是队列中最小值。然后每次都取堆顶元素,删去堆顶元素,并用队列中最后一个元素补在堆顶位置,再对堆顶位置进行“下潜操作”,这样又能保持最小堆的状态,循环操作,就能将原数组排序
public static void heapSort(int array[]) {
int tempArray[] = Arrays.copyOf(array, array.length);
//对非叶子节点进行下潜操作,在原队列建立最小堆
for (int i = (tempArray.length - 1) / 2; i >= 0; i --) {
adjustDown(tempArray, i, tempArray.length - 1);
}
//也可以通过从第一个元素开始,每一个元素执行“上潜操作”,来简历堆。上潜操作适合在一个堆的队列末尾增加元素,调整堆的情况。
// for (int i = 0; i < tempArray.length; i ++) {
// adjustUp(tempArray, i);
// }
//每次都取出堆顶元素,再用队列末尾补在堆顶位置,对堆顶位置进行下潜操作,这样又能保证堆顶元素是最小的啦,再循环操作,直至数组元素全部排序完
for (int i = 0; i < array.length; i ++) {
array[i] = tempArray[0];
tempArray[0] = tempArray[tempArray.length - 1 - i];
adjustDown(tempArray, 0, tempArray.length - 2 - i);
}
}
private static void adjustDown(int array[], int index, int maxIndex) {
int temp = array[index];
int child = index * 2 + 1;
while(child <= maxIndex) {
if (child < maxIndex && array[child + 1] < array[child]) {
child ++;
}
if(temp < array[child]) {
break;
}
array[(child - 1)/2] = array[child];
child = child * 2 + 1;
}
array[(child - 1) / 2] = temp;
}
public static void adjustUp(int array[], int index) {
int temp = array[index];
while((index - 2) / 2 >= 0) {
if(temp >= array[(index - 1) / 2]) {
break;
}
array[index] = array[(index - 1) / 2];
index = (index - 1) / 2;
}
array[index] = temp;
}