有序和无序数组的二分搜索算法

题目意思

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

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

对于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 long
using 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
}

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>
时间: 2024-10-02 06:00:41

有序和无序数组的二分搜索算法的相关文章

(每日算法)LeetCode --- Search in Rotated Sorted Array(旋转数组的二分检索)

Search in Rotated Sorted Array I && II Leetcode 对有序数组进行二分查找(下面仅以非递减数组为例): int binarySort(int A[], int lo, int hi, int target) { while(lo <= hi) { int mid = lo + (hi - lo)/2; if(A[mid] == target) return mid; if(A[mid] < target) lo = mid + 1;

java面向对象的有序数组和无序数组的比较

package aa; class Array{ //定义一个有序数组 private long[] a; //定义数组长度 private int nElems; //构造函数初始化 public Array(int max){ a = new long[max]; nElems = 0; } //size函数 public int size(){ return nElems; } //定义添加函数 public void insert(long value){ //将value赋值给数组成员

『嗨威说』算法设计与分析 - 算法第二章上机实践报告(二分查找 / 改写二分搜索算法 / 两个有序序列的中位数)

本文索引目录: 一.PTA实验报告题1 : 二分查找 1.1 实践题目 1.2 问题描述 1.3 算法描述 1.4 算法时间及空间复杂度分析 二.PTA实验报告题2 : 改写二分搜索算法 2.1 实践题目 2.2 问题描述 2.3 算法描述 2.4 算法时间及空间复杂度分析 三.PTA实验报告题3 : 两个有序序列的中位数 3.1 实践题目 3.2 问题描述 3.3 算法描述 3.4 算法时间及空间复杂度分析 四.实验心得体会(实践收获及疑惑) 一.PTA实验报告题1 : 二分查找 1.1 实践

二分——无序数组快速查找第K小的数

#1133 : 二分·二分查找之k小数 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在上一回里我们知道Nettle在玩<艦これ>,Nettle的镇守府有很多船位,但船位再多也是有限的.Nettle通过捞船又出了一艘稀有的船,但是已有的N(1≤N≤1,000,000)个船位都已经有船了.所以Nettle不得不把其中一艘船拆掉来让位给新的船.Nettle思考了很久,决定随机选择一个k,然后拆掉稀有度第k小的船. 已知每一艘船都有自己的稀有度,Nettle现在把所有

有序数组的二分查找

二分查找的优点是比较次数少,查找速度快,但是在查找之前必须建立有序表.另外,二分查找只适用于顺序存储的有序表,而不适用于链接存储的有序表. 假设:给定一个按从小到大排序的数组P,对分查找某个元素的位置. 二分查找的过程为首先将x和数组的中间项进行比较,若x小于中间项的值,则在线性表的前半部分进行二分查找:若x大于中间项的值,则在线性表的后半部分进行二分查找:若x等于中间项的值,则查找结束.若待二分的子表长度为0时仍然没有找到这个元素,则说明数组中没有x. java代码 <span style=&qu

(二分查找思想)从有序递增旋转数组45679123 中找到数字6的位置

#define _CRT_SECURE_NO_WARNINGS 1 #include <iostream> using namespace std; /** * 从有序递增旋转数组45679123 中找到数字6的位置 * 数组递增 但有旋转 * 二分查找思想 * 时间复杂度小于O(N) * {7,8,9,10,1,2,3,4,5,6} *************/ int find_revolve_array(const int arr[], int len, int value) { if

二分搜索算法

题目:设 a [ 0 : n - 1 ] 是一个已排好序的数组.请改写二分搜索算法,使得当搜索元素 x 不在数组中时,返回小于 x 的最大元素的位置 i 和大于 x 的最小元素位置 j .当搜索元素在数组中时, i 和j相同,均为 x 在数组中的位置.并对自己的程序进行复杂性分析. import java.util.Arrays; import java.util.Scanner; public class Main { static int x;// 需要查找的数据 // 形参i,j是数组下标

有1,2,3一直到n的无序数组,排序

题目:有1,2,3,..n 的无序整数数组,求排序算法.要求时间复杂度 O(n), 空间复杂度O(1). 分析:对于一般数组的排序显然 O(n) 是无法完成的. 既然题目这样要求,肯定原先的数组有一定的规律,让人们去寻找一种机会. 例如:原始数组: a = [ 10, 6,9, 5,2, 8,4,7,1,3 ] ,如果把它们从小到大排序且应该是 b = [1,2,3,4,5,6,7,8,9,10 ],也就是说: 如果我们观察 a --> b 的对映关系是: a[i] 在 b 中的位置是 a[i]

改写二分搜索算法

本算法的题目来源<计算机算法与分析> 设a[0:n-1]是已排好序的数组,请改写二分搜索算法,使得当x不在数组中时,返回小于x的最大元素位置i和大于x的最小元素位置j.当搜索元素在数组中时,i和j相同,均为x在数组中的位置. 提示:若x小于全部数值,则输出:-1 0 若x大于全部数值,则输出:n-1的值 n的值. 一.以下附上源码和分析 1 #include <iostream> 2 using namespace std; 3 void ch_bin_search_while(i