有序和无序数组的二分搜索算法+select第k小的元素

来源:互联网 发布:关闭端口 编辑:程序博客网 时间:2024/06/06 07:12

题目意思

1、给定有序数组A和关键字key,判断A中是否存在key,如果存在则返回下标值,不存在则返回-1。

2、给定无序数组A和关键字key,判断A中是否存在key,如果存在则返回1,不存在则返回0。

3、给定无序数组A和下标k,找到A[k]并输出,渐进时间O(n),基于快排的划分函数的二分思想。

对于1、2问题,我们都可以简单的写出O(n)的从头到尾为的扫描算法,这里就不在累赘,这里我们讨论的是基于二分查找的算法,使其时间在渐进意义上达到O(logn)。

对于有序的数组,很“容易”写出基于二分的函数、

那么问题2,对于无序数组,怎么查找呢?这里我们用到了快速排序的划分原则。算法大致如下:

函数调用BinarySearch(a,n,key); a[1..n]

在无序数组a[n]中查找x是否存在,如果存在返回1,不存在返回0

这里我们用到快速排序中的划分规则,大致意思如下

将数组A[p..r]划分为两个字数组A[p..q-1]和A[q+1..r],使得

A[p..q-1]中的每个元素都小于等于A[q],并且,小于等于A[q+1..r]

对于查找关键字key,if(key==A[q]) return 1;

if(key<A[q])查找字数组A[p..q-1]

if(key>A[q])查找字数组A[q+1..r]


代码和注释:


<span style="font-size:18px;">/**  *@xiaoran  */#include<iostream>#include<cstdio>#include<map>#include<cstring>#include<string>#include<algorithm>#include<queue>#include<vector>#include<stack>#include<cstdlib>#include<cctype>#include<cmath>#define LL long longusing namespace std;/** *二分查找 *函数调用BinarySearch(a,0,n-1,key); *在有序数组a[n]中查找x是否存在,如果存在返回下标,不存在返回-1 */int BinarySearch(int *a,int left,int right,int &key){    //在有序数组a[n]中查找x是否存在,如果存在返回下标,不存在返回-1    while(left<=right){        int mid=(left+right)/2;        if(key==a[mid]) return mid;        else if(key>a[mid]) left=mid+1;        else right=mid-1;    }    return -1;}/** *二分查找 *函数调用BinarySearch(a,n,key); *在无序数组a[n]中查找x是否存在,如果存在返回1,不存在返回0 *这里我们用到快速排序中的划分规则,大致意思如下 *将数组A[p..r]划分为两个字数组A[p..q-1]和A[q+1..r],使得 *A[p..q-1]中的每个元素都小于等于A[q],并且,小于等于A[q+1..r] *对于查找关键字key,if(key==A[q]) return 1; *if(key<A[q]) 查找字数组A[p..q-1] *if(key>A[q]) 查找字数组A[q+1..r] */int Binary_Init(int *a,int p,int r){    int tmp,i,j;    tmp=a[p];    i=p+1; j=r;    while(true){        while(a[i]<=tmp) ++i;        while(a[j]>tmp) --j;        if(j<=i) break;        else{            swap(a[i],a[j]);            ++i; --j;        }    }    swap(a[p],a[j]);//关键字放到中间    return j;//返回关键字的位置}int BinarySearchPlus(int *a,int l,int r,int key){    if(l<r){        int mid=Binary_Init(a,l,r);        //cout<<a[mid]<<" "<<key<<endl;        if(a[mid]==key) return 1;//Yes        else if(key<a[mid]){//搜索左边一半            return BinarySearchPlus(a,l,mid-1,key);        }        else{//key>a[mid],//搜索右边一半            return BinarySearchPlus(a,mid+1,r,key);        }    }    if(l==r) return a[l]==key;//只有一个元素    return 0;//No}/** *无序数组中的select(A,p,r,k)选择数组中的第k小的元素 */int Partition(int *A,int p,int r){    int i,j,x;    i=p+1; j=r;    x=A[p];    while(true){        while(A[i]<=A[p]) ++i;        while(A[j]>A[p]) --j;        if(j<=i) break;        else{            swap(A[i],A[j]);//交换两个违反规则的值            ++i; --j;        }    }    swap(A[p],A[j]);    return j;}/** *给出一个无序的数组,在渐进时间O(n)的情况下, *选出第k小的元素的值 */int Select_k(int *A,int p,int r,int k){    if(k<1||k>r) return -1;    int index;    if(p==r) return A[p];    int q=Partition(A,p,r);    index=q-p+1;//找到的是第几个值    //cout<<index<<endl;    if(index==k){        return A[q];    }    else if(index<k){//此时向右查找        return Select_k(A,q+1,r,k-index);//查找的是相对位置的值,k在右段中的下标为k-index    }    else{        return Select_k(A,p,q-1,k);    }}int main(){    int A[9]={0,9,4,3,12,5,34,55,44};    int key;    while(cin>>key){        cout<<BinarySearch(A,1,8,key)<<endl;        cout<<BinarySearchPlus(A,1,8,key)<<endl;    }return 0;}</span>


1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 膨胀螺丝孔大了怎么办 戒指不圆了怎么办妙招 眼镜框的腿断了怎么办 弹簧腿眼镜坏了怎么办 vps搭建ss被墙怎么办 注塑机螺杆黏料怎么办 分解师耐久度0了怎么办 有鼻涕擤不出来怎么办 擤鼻涕耳朵堵了怎么办 脸用什么都过敏怎么办 1岁宝宝流清鼻涕怎么办 2岁宝宝流清鼻涕怎么办 3岁儿童流清鼻涕怎么办 鼻子老是流清水鼻涕怎么办 5岁儿童感冒鼻塞怎么办 3岁宝宝感冒鼻塞怎么办 宝宝9个月流鼻涕怎么办 鼻涕又黄又粘稠怎么办 鼻子一直流黄水怎么办 宝宝眼屎多又黄怎么办 宝宝痰多鼻涕多怎么办 小孩痰多鼻涕多怎么办 用qq登不了微博怎么办 中国银行u盾丢了怎么办 我的世界遇见him怎么办 考军校年龄超了怎么办 dnf组队就红电脑怎么办 九阳高压锅漏气怎么办 晋江买了防盗章怎么办 开车撞了人应该怎么办 开车撞了人没钱怎么办 驾照扣分12分后怎么办 车被交警拖走了怎么办 符石耐久没了怎么办 冒险岛2老是掉线怎么办 冒险岛老是掉线怎么办 冒险岛2延迟高怎么办 高速超速扣6分怎么办 优酷视频有密码怎么办 斗鱼直播很卡怎么办 鼠标的滑轮坏了怎么办