21年考研王道数据结构2-9算法:通过折半查找指定值X并根据结果进行操作(两种方法)

题目:线性表中的元素递增有序且按照顺序存储在计算机中,要求设计一种算法在最少时间内查找到数值为X的元素,若找到则将其与后继元素位置交换,若找不到则将其插入表中使表中元素仍递增有序

分析:要求最少时间则采用折半查找,分为递归和循环两种。若找到元素后该元素位置为最后一个则不做处理,若找不到该元素后插入该元素到数组中必会引起指针错误,因为数组大小为a[n],插入后变成a[n+1]引发内存未初始化的错误,所以要挤掉数组最后一个元素后再插入

递归方法

#include<iostream>
using namespace std;

int ch(int a[], int left, int right, int x,int len)
{
    if (left > right) {
        cout<<"left>right! break;"<<endl;
            return -1;
    }
    //system("pause");
    cout <<"now is "<<(left+right)/2<<", a[i]= "<<a[(left+right)/2]<< ", left= " << left << 
     ", right= " << right << ", x= " << x <<", len="<<len<< endl;
    if (x == a[(left + right) / 2]&&((left + right) / 2+1 !=len)){ 
//找到X,排除掉X为最后一个元素的情况后开始和后一个元素交换位置
        cout << "index=" << (left + right) / 2 + 1 << endl;
        int temp = a[(left + right) / 2];
        a[(left + right) / 2] = a[(left + right) / 2 + 1]; 
//不排除上述的情况话,会在此处出现内存错误,
//因为a[(left+right)/2]=a[9]=19,a[(left+right)/2+1]=a[10]未定义
        a[(left + right) / 2 + 1] = temp;
        return 1;

    }
    else if (x != a[(left + right) / 2] && left == right) { 
//未找到X,开始插入
        cout << "not found!" << endl;
        for (int i = len-1;i > (left + right) / 2; i--) 
//这里i不能是len=10,因为同样a[10]无定义
        {
           a[i] = a[i - 1]; 
        } 
        a[(left + right) / 2] = x;
        return 0;
    }
    else if (x > a[(left + right) / 2]) return ch(a, (left + right) / 2+1, right, x,len);
    else if (x < a[(left + right) / 2]) return ch(a, left, (left + right) / 2-1, x,len);
}


int main()
{
    int a[] = { 1,3,5,7,9,11,13,15,17,19 };
    cout << "sizeof(a)/sizeof(a[0])= " << sizeof(a) / sizeof(a[0]) << " sizeof(a)=" << sizeof(a) << endl;
    cout << "result=" << ch(a,0,9,0,sizeof(a)/sizeof(a[0])) << endl;
    for (auto i : a)
        cout << " " << i;
}

 

循环方法:注释参考上面的程序

#include <iostream>
using namespace std;


int tot(int a[], int len,int x)
{
    int left = 0, right = len - 1,mid=0;
    while (left <= right)
    {
        //system("pause");
        mid = (left+right) / 2;
        cout << "mid=" << mid << ",a[mid]=" << a[mid] << ",left=" << left << ",right=" << right << endl;
        if (x == a[mid] )
        {
            cout << "find x";
            if (mid != len - 1)
            {
                int temp = a[mid];
                a[mid] = a[mid + 1];
                a[mid + 1] = temp;
                cout << "\nchange finish" << endl;
                return 1;
            }
            cout << ",but x is the last element" << endl;
            return 2;
        }
        else if (x > a[mid])
            left = mid + 1;
        else if (x < a[mid])
            right = mid;
        if (mid == right && mid == left) 
            //后面测试发现找不到X后会有死循环,才加上去的
        {
            break;
        }
    }
    cout << "not found,insert X" << endl;
    int i;
    for ( i = len - 1; i > mid; i--)
        a[i] = a[i-1];
    a[mid] = x;
    return 0;
}

int main()
{

    int a[] = { 1,3,5,7,9,11,13,15,17,19 };
    cout << "sizeof(a)/sizeof(a[0])= " << sizeof(a) / sizeof(a[0]) << " sizeof(a)=" << sizeof(a) << endl;
    //ch(a,0,9,0,sizeof(a)/sizeof(a[0]));
    tot(a, sizeof(a) / sizeof(a[0]), 20);
    for (auto i : a)
        cout << " " << i;
}

但是这个题有一点问题,当要查询的值X大于数组的最后一个元素时,按照题目要求也要把X插入到数组中,只好挤掉数组最后的元素19。答案的方法是循环法,但是也没给出如何处理这种情况的方法,它也是挤掉的最后一位来把X放在末尾。

posted @ 2020-06-28 01:54  北陌南旬  阅读(260)  评论(0)    收藏  举报