分而治之(divide - conquer);每个递归过程涉及三个步骤
第一, 分解: 把待排序的 n 个元素的序列分解成两个子序列, 每个子序列包括 n/2 个元素.
第二, 治理: 对每个子序列分别调用归并排序MergeSort, 进行递归操作
第三, 合并: 合并两个排好序的子序列,生成排序结果.
/**
* 分治算法思路: 将一个大问题,分解成同样的多个小问题,解决每个小问题,最后合并就解决了大问题。
* @param arr
* @param low
* @param high
*/
public static void mergeSort(int arr[], int low, int high) {
int midle = (low + high) >>> 1;
if (low < high) { // 控制至少两个才能分解合并
// 分解
mergeSort(arr, low, midle);
mergeSort(arr, midle + 1, high);
//合并
merge(arr, low, midle, high);
}
}
// 合并
public static void merge(int arr[], int low, int midle, int high) {
int center = midle + 1; // 右边数组的起始位置
int temp[] = new int[high - low + 1]; // 临时数组
int index = 0;
while (low <= midle && center <= high) {
if (arr[low] < arr[center]) {
temp[index++] = arr[low++];
} else if (arr[low] > arr[center]) {
temp[index++] = arr[center++];
} else {
temp[index++] = arr[low++];
temp[index++] = arr[center++];
}
}
while (low <= midle) { // 左边还有剩余
temp[index++] = arr[low++];
}
while (center <= high) { // 右边还有剩余
temp[index++] = arr[center++];
}
copy(arr, temp, high); // 拷贝元素
}
public static void copy(int arr[], int temp[], int high) {
for (int i = temp.length - 1; i >= 0; i--) {
arr[high--] = temp[i];
}
}
快速排序是冒泡排序的改进版,也是最好的一种内排序,在很多面试题中都会出现,也是作为程序员必须掌握的一种排序方法。
思想:1.在待排序的元素任取一个元素作为基准(通常选第一个元素,但最的选择方法是从待排序元素中随机选取一个作为基准),称为基准元素;
2.将待排序的元素进行分区,比基准元素大的元素放在它的右边,比其小的放在它的左边;
3.对左右两个分区重复以上步骤直到所有元素都是有序的。
所以我是把快速排序联想成东拆西补或西拆东补,一边拆一边补,直到所有元素达到有序状态。
/**
*
* void QuickSort(SeqList R,int low,int high) {
int pivotpos; //划分后的基准记录的位置
if(low<high){ //仅当区间长度大于1时才须排序
pivotpos=Partition(R,low,high); //对R[low..high]做划分
QuickSort(R,low,pivotpos-1); //对左区间递归排序
QuickSort(R,pivotpos+1,high); //对右区间递归排序
}
}
*/
public static void quickSort(int low, int high, int arr[]) {
int position;
if (low < high) {
position = partition(arr, low, high);
quickSort(low, position-1, arr);
quickSort(position+1, high, arr);
}
}
private static int partition(int arr[], int low, int high) {
int res = arr[low];
while (low != high) {
while (low < high && arr[high] >= res) {
high--;
}
arr[low] = arr[high];
while (low < high && arr[low] <= res) {
low++;
}
arr[high] = arr[low];
}
arr[low] = res; // 基数归位
return low;
}