快速排序、归并排序、二分

1.快速排序

解题代码

#include<iostream>
 
using namespace std;
 
const int N = 1e6 + 10;
 
int n;
int q[N];
 
void quick_sort(int q[],int l,int r)
{
    if(l>=r)return;
    
    int x = q[(l+r)/2], i = l - 1, j = r + 1;
    while(i<j)
    {
        do i++;while(q[i]<x);
        do j--;while(q[j]>x);
        if(i<j) swap(q[i],q[j]);
    }
    
    quick_sort(q,l,j);
    quick_sort(q,j+1,r);
}
 
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%d",&q[i]);
    
    quick_sort(q,0,n-1);
    
    for(int i=0;i<n;i++) printf("%d ",q[i]);
    
    return 0;
}

分析代码

#include<iostream>
 
using namespace std;
 
const int N = 1e6 + 10;//1*10^6+10=1000010
 
int n;
int q[N];
 
void quick_sort(int q[],int l,int r)
{
    if(l>=r)return;
    
    int x = q[(l+r)/2], i = l - 1, j = r + 1;//指针i,j
    //cout<<"l="<<l<<" r="<<r<<endl;
    //cout<<"当前序列";
    //for(int i=l;i<=r;i++) printf("%d ",q[i]);
    //cout<<endl;
    //cout<<"x=q[l]="<<x<<endl;
    while(i<j)
    {
        do{i++;/*cout<<"while循环中i="<<i<<endl;*/}while(q[i]<x);
        //do i++;while(q[i]<x);
        //do j--;while(q[j]>x);
        do{j--;/*cout<<"while循环中j="<<j<<endl;*/}while(q[j]>x);
        //cout<<"两次循环后i="<<i<<" j="<<j<<endl;
        if(i<j) swap(q[i],q[j]);
    }
   // cout<<"j="<<j<<"处理后的序列";
    //for(int i=l;i<=r;i++) printf("%d ",q[i]);
    //cout<<endl;
    //递归处理左右两端
    quick_sort(q,l,j);
    quick_sort(q,j+1,r);
}
 
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%d",&q[i]);
    
    quick_sort(q,0,n-1);
    
    for(int i=0;i<n;i++) printf("%d ",q[i]);
    
    return 0;
}

2.归并排序

//输入
7
6 4 3 7 5 1 2

//输出
1 2 3 4 5 6 7

归并:解题代码

#include<iostream>
 
using namespace std;
 
const int N=1000010;
 
int n;
int q[N],tmp[N];
 
 
void merge_sort(int q[],int l,int r)
{
    if(l>=r) return;
    
    int mid=l+r>>1;
    
    merge_sort(q,l,mid),merge_sort(q,mid+1,r);
    
    int k=0,i=l,j=mid+1;
    while(i<=mid && j<=r)
        if(q[i]<=q[j]) tmp[k++]=q[i++];
        else tmp[k++]=q[j++];
    while(i<=mid) tmp[k++]=q[i++];
    while(j<=r) tmp[k++]=q[j++];
    
    for(i=l,j=0;i<=r;i++,j++) q[i]=tmp[j];
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%d",&q[i]);
    
    merge_sort(q,0,n-1);
    
    for(int i=0;i<n;i++) printf("%d ",q[i]);
 
    return 0;
}

归并:分析代码

#include<iostream>
 
using namespace std;
 
const int N=1000010;
 
int n;
int q[N],tmp[N];
 
void merge_sort(int q[],int l,int r)
{
    cout<<"函数内部l="<<l<<",r="<<r<<endl;
    if(l>=r)
    {
        cout<<"回溯,l="<<l<<",r="<<r<<endl;
        return;
    }
    
    //取上中位数
    int mid = l + r >> 1;
    //用递归拆分,直到拆为两个数
    cout<<"递归左边"<<endl;
    cout<<"递归前l="<<l<<",r="<<r<<" mid="<<mid<<endl;
    merge_sort(q,l,mid);
    cout<<"递归右边"<<endl;
    cout<<"递归前l="<<l<<",r="<<r<<" mid="<<mid<<endl;
    merge_sort(q,mid+1,r);
    cout<<"递归结束"<<endl;
    //cout<<"递归后l="<<l<<",r="<<r<<l<<" mid="<<mid<<endl;
    //k是tmp[]有多少个数,k[0]=q[2]
    int k=0,i=l,j=mid+1;
    //合并
    cout<<"合并前i="<<i<<" j="<<j<<endl;
    while(i<=mid && j<=r)
        if(q[i]<=q[j])
        {
            cout<<"给tmp赋值 tmp["<<k<<"]=q["<<i<<"]"<<endl;
            tmp[k++]=q[i++];
        }
        else tmp[k++]=q[j++];
    while(i<=mid) tmp[k++]=q[i++];
    while(j<=r) tmp[k++]=q[j++];
    
    for(i=l,j=0;i<=r;i++,j++) q[i]=tmp[j];
}
 
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%d",&q[i]);
    
    merge_sort(q,0,n-1);
    
    for(int i=0;i<n;i++) printf("%d ",q[i]);
    
    return 0;
}

3.二分

二分-解题代码

#include <iostream>

using namespace std;

const int N = 100010;

int n, m;
int q[N];

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 0; i < n; i ++ ) scanf("%d", &q[i]);

    while (m -- )
    {
        int x;
        scanf("%d", &x);

        int l = 0, r = n - 1;
        while (l < r)
        {
            int mid = l + r >> 1;
            if (q[mid] >= x) r = mid;
            else l = mid + 1;
        }

        if (q[l] != x) cout << "-1 -1" << endl;
        else
        {
            cout << l << ' ';

            int l = 0, r = n - 1;
            while (l < r)
            {
                int mid = l + r + 1 >> 1;
                if (q[mid] <= x) l = mid;
                else r = mid - 1;
            }

            cout << l << endl;
        }
    }

    return 0;
}

二分-分析代码

#include <iostream>

using namespace std;

const int N = 100010;

int n, m;//m为查询的次数
int q[N];

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 0; i < n; i ++ ) scanf("%d", &q[i]);

    while (m -- )
    {
        int x;//查询x在数列中的开始和结束位置
        scanf("%d", &x);
   
        int l = 0, r = n - 1;
        while (l < r)
        {
            cout<<"mid为上中位数"<<endl;
            int mid = l + r >> 1;//上中位数,较小位置,作结束位
            if (q[mid] >= x)  //较小位置的数>=x
            {
                cout<<"前半部分找"<<endl;
                r = mid;   //x在mid 前面,下一次应该在前半部分找
            }
            else  //较小位置的数<x
            {
                cout<<"后半部分找"<<endl;
                l = mid + 1; //x在mid后面,下一次应该在后半部分找
            }
            cout<<x<<"可能在l="<<l<<",r="<<r<<endl;
        }

        if (q[l] != x) cout << "-1 -1" << endl;
        else
        {
            cout<<"最终x开始的位置在";
            cout << l << ' '; //开始的位置

            int l = 0, r = n - 1;
            while (l < r)  
            {
                cout<<"mid为下中位数"<<endl;
                int mid = l + r + 1 >> 1;//下中位数,较大位置,作开始位
                if (q[mid] <= x)  //较大位置的数<=x
                {
                    cout<<"后半部分找"<<endl;
                    l = mid;  //x在mid后面,下一次应该在后半部分找
                }
                else  //较大位置的数>x
                {
                    cout<<"前半部分找"<<endl;
                    r = mid - 1;  //x在mid 前面,下一次应该在前半部分找
                }
                cout<<x<<"可能在l="<<l<<",r="<<r<<endl;
            }
            
            cout<<"最终x结束的位置在";
            cout << l << endl;  //结束的位置
        }
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值