有序和无序数组的二分搜索算法+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
- 有序和无序数组的二分搜索算法+select第k小的元素
- 求两个有序数组的第k小元素
- 求两个有序数组的中位数和者第k小元素
- 有序数组和无序数组的二分查找
- 一个无序数组中第K大的元素
- 由无序数组中找到第K 大的元素
- 无序数组中找到第k大的元素
- 算法导论:快速找出无序数组中第k小的数
- 寻找单个无序数组中第K小的数字
- 无序数组找第k小的数
- 【算法】快速排序/数组第K小的元素
- 数组第k小的元素和数组前k小元素
- 求两个有序数组的中位数或者第k小元素
- 从两个有序数组的并集中寻找第k小元素
- 从两个有序数组的并集中寻找第k小元素
- [LeetCode题解]从两个有序数组的并集中寻找第k小元素
- 每天一道算法题目(18)——取等长有序数组的上中位数和不等长有序数组的第k小的数
- 二分求两个有序数组第k大的数
- LeetCode - Rotate Array
- Google C++ 风格指南 - 中文版
- 求 2/1+3/2+5/3+8/5+13/8+…的前20项和
- Android FoldingLayout 折叠布局 原理及实现(二)
- hdoj 2120 Ice_cream's world I 【并查集判断成环数】
- 有序和无序数组的二分搜索算法+select第k小的元素
- TCP滑动窗口 - 动画演示
- css+div
- [NOI2011]兔农(斐波那契数列+乘法逆+矩阵加速)
- 数据结构学习第二课
- ejb
- java io 不同线程之间的通信
- 核心动画
- java模式之适配器模式