基础算法之快排、归并、二分

143 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 1 天,点击查看活动详情

一、快速排序

快速排序基于分治思想,时间复杂度(nlogn)

快排的步骤:

  1. 确定分界点:q[left]、q[(left + right) / 2]、q[right] 三个其中一个都行
  2. 调整(划分)区间(快排的重点):把小于pivot的放在左区间,大于pivot的放在右区间
  3. 递归处理左右两个区间

算法思想:

在区间左右两端定义i和j两个指针,假设pivot为x,当i下标对应的元素小于x时i++,当i下标对应的元素不小于x时i不变,则开始移动j,当j下标对应的元素大于x时j--,当j下标对应的元素不大于x时j不变,交换i和j下标对应的元素,重复以上操作直到i和j相遇为止。

快速排序模板

void quick_sort(int q[], int left, int right){
    if(left >= right)
	return;
    int i = left - 1, j = right + 1, pivot = q[left + right >> 1];
    while(i < j){
        do{
            i++;
        }while(q[i] < pivot);
        do{
            j--;
        }while(q[j] > pivot);
        if(i < j)
            swap(q[i], q[j]);
    }
    quick_sort(q, left, j);
    quick_sort(q, j + 1, right);
}

二、归并排序

归并排序基于分治思想,时间复杂度(nlogn)

归并步骤:

  1. 确定分界点:mid = left + (right - left) / 2
  2. 递归排序左右区间
  3. 归并(归并排序的重点):把两个有序的数组合并成一个有序的数组(合二为一)

算法思想:

归并简单来说其实就是比较两个数组,把两个数组中比较小的数插入到新的数组中

归并排序模板

void merge_sort(int q[], int left, int right){
    if(left >= right)
        return;
    int mid = left + (right - left) / 2; //(right + left) >> 1;
    merge_sort(q, left, mid);
    merge_sort(q, mid + 1, right);
    int k = 0, i = left, j = mid + 1;
    //两两比较
    while(i <= mid && j <= right){
        if(q[i] <= q[j])
            temp[k++] = q[i++];
        else
            temp[k++] = q[j++];
    }
    //把两个数组剩余的元素插入到temp数组
    while(i <= mid)
        temp[k++] = q[i++];
    while(j <= right)
	temp[k++] = q[j++];
    //将排序结果赋回给原数组
    for(int i = left, j = 0; i <= right; i++, j++)
        q[i] = temp[j];
}

三、二分查找

二分查找的本质是在某种性质下找到满足和不满足的边界

二分查找模板

bool check(int x) {/* ... */} //检查x是否满足某种性质
 
// 区间[left, right] 被划分成[left, mid] 和 [mid + 1, right]时使用
int bsearch_1(int left, int right){
    while(left < right){
    int mid = left + right >> 1;
    if(check(mid))
        right = mid;
    else
        left = mid + 1;
    }
    return left;
}
 
// 区间[left, right] 被划分成[left, mid - 1] 和 [mid, right]时使用
int bsearch_1(int left, int right){
    while(left < right){
    int mid = left + right + 1 >> 1;
    if(check(mid))
        left = mid;
    else
        right = mid - 1;
    }
    return left;
}