题目
(二分查找的实现)请尝试用你实现的顺序存储List实现二分查找。List中的Record包含key和other部分。其中key为英文单词,other为单词的中文解释。
【输入】
第一行,查询目标target(英文单词)
第二行,若干条包含key(string)和other(string)的序列,序列按照key的升序排列;(单词数量小于2000)
【输出】查询目标所在的下标,查询目标的内容(key和other),若单词不存在则输出-1即可。
例如
【输入】
wait
computer 电脑 eye 眼睛 hello 你好 train 火车 wait 等待 zebra 斑马
【输出】
4
wait 等待
【输入】
apple
computer 电脑 eye 眼睛 hello 你好 train 火车 wait 等待 zebra 斑马
【输出】
-1 //不存在
代码
面向过程,代码较长。
#include <bits/stdc++.h>
using namespace std;
enum Error_code{underflow,overflow,error,success,fail,not_present};
const int max_list = 2010;
class Record;
class Key
{
string key;
public:
Key(string x = " ");
Key(const Record &r);
string the_key()const;
};
class Record
{
public:
operator Key();//implicit conversion
Record(string x = " ",string y = " ");
string the_key()const;
string the_other()const;
private:
string key;
string other;
};
typedef Record List_entry;
bool operator == (const Key &x,const Key &y);
bool operator > (const Key &x,const Key &y);
bool operator < (const Key &x,const Key &y);
bool operator <= (const Key &x,const Key &y);
bool operator >= (const Key &x,const Key &y);
bool operator == (const Record &x,const Record &y);
bool operator > (const Record &x,const Record &y);
bool operator < (const Record &x,const Record &y);//别忘了Record的运算符重载!!!
class List
{
public:
List();
int size()const;
bool full()const;
bool empty()const;
void clear();
void traverse(void(*visit)(List_entry &));
Error_code retrieve(int position,List_entry &x)const;
Error_code replace(int position,const List_entry &x);
Error_code remove(int position,List_entry &x);
Error_code insert(int position,const List_entry &x);
protected:
int count;
List_entry entry[max_list];
};
class Ordered_list:public List
{
public:
Error_code insert(const Record &data);
Error_code insert(int position,const Record &data);
Error_code replace(int position,const Record &data);
};
Error_code recursive_binary(const Ordered_list &the_list,const Key &target,int bottom,int top,int &position)
{
Record data;
if (bottom <= top)
{
int mid = (bottom + top) / 2;
the_list.retrieve(mid,data);
if (data == target)
{
position = mid;
return success;
}
else if (data < target)
return recursive_binary(the_list,target,mid + 1,top,position);
else
return recursive_binary(the_list,target,bottom,mid - 1,position);
}
else return not_present;
}
int main()
{
string str,tmp_a,tmp_b;
cin >> str;
Key target(str);
int bottom,top,position;
Ordered_list mylist;
while (cin >> tmp_a >> tmp_b)//input
{
mylist.insert(Record(tmp_a,tmp_b));
}
bottom = 0;
top = mylist.size() - 1;
position = bottom;
if (recursive_binary(mylist,target,bottom,top,position) == success)
{
Record tmp;
mylist.retrieve(position,tmp);
cout << position << endl << tmp.the_key() << " " << tmp.the_other() << endl;
}
else cout << -1 << endl;
return 0;
}
Key::Key(string x)
{
key = x;
}
Key::Key(const Record &r)
{
key = r.the_key();
}
string Key::the_key()const
{
return key;
}
bool operator == (const Key &x,const Key &y)
{
return x.the_key() == y.the_key();
}
bool operator > (const Key &x,const Key &y)
{
return x.the_key() > y.the_key();
}
bool operator < (const Key &x,const Key &y)
{
return x.the_key() < y.the_key();
}
bool operator <= (const Key &x,const Key &y)
{
return x.the_key() <= y.the_key();
}
bool operator >= (const Key &x,const Key &y)
{
return x.the_key() >= y.the_key();
}
bool operator == (const Record &x,const Record &y)
{
return x.the_key() == y.the_key();
}
bool operator > (const Record &x,const Record &y)
{
return x.the_key() > y.the_key();
}
bool operator < (const Record &x,const Record &y)
{
return x.the_key() < y.the_key();
}
Record::Record(string x,string y)
{
key = x;
other = y;
}
Record::operator Key()
{
Key tmp(key);
return tmp;//!!一定要return!
}
string Record::the_key()const
{
return key;
}
string Record::the_other()const
{
return other;
}
List::List()
{
count = 0;
}
int List::size()const
{
return count;
}
bool List::full()const
{
return count == max_list;
}
bool List::empty()const
{
return count == 0;
}
void List::clear()
{
count = 0;
}
Error_code List::insert(int position,const List_entry &x)
{
if (full()) return overflow;
if (position < 0 || position > count) return error;//只有这里是>!其余是>=
for (int i = count - 1; i >= position; i--) entry[i+1] = entry[i];
entry[position] = x;
count++;
return success;
}
Error_code List::remove(int position,List_entry &x)
{
if (empty()) return overflow;
if (position < 0 || position >= count) return error;
x = entry[position];
for (int i = position; i < count - 1; i++) entry[i] = entry [i + 1];
count--;
return success;
}
Error_code List::replace(int position,const List_entry &x)
{
if (position < 0 || position >= count) return error;
entry[position] = x;
return success;
}
Error_code List::retrieve(int position,List_entry &x)const
{
if (position < 0 || position >= count) return error;
x = entry[position];
return success;
}
Error_code Ordered_list::insert(const Record &data)
{
int s = size();
int position;
for (position = 0; position < s; position++)
{
Record list_data;
retrieve(position,list_data);
if (data < list_data) break;
}
return List::insert(position,data);
}
Error_code Ordered_list::insert(int position,const Record &data)
{
Record list_data;
if (position > 0)
{
retrieve(position - 1,list_data);
if (data < list_data) return fail;
}
if (position < size())
{
retrieve(position,list_data);
if (data < list_data) return fail;
}
return List::insert(position,data);
}
Error_code Ordered_list::replace(int position,const Record &data)
{
if (position < 0 || position >= count) return error;
Record list_data;
if (position > 0)
{
retrieve(position - 1,list_data);
if (data < list_data) return fail;
}
if (position < size() - 1)
{
retrieve(position,list_data);
if (data < list_data) return fail;
}
entry[position] = data;
return success;
}
注意
- c++里,输入不知道长度,直接while(cin >> a >> b) 即可。
- 互相调用的class先把声明写在上边。
- 写了新的class后,如果有运算操作,一定要记得运算符重载!!!
- 解决Record == Key有两种方法:
①:
Key(const Record &r)
{
key = r.the_key();
}
string Record::the_key()const
{
return key;
}
②:
operator Key()
{
Key tmp(key);
return tmp;
}
两种方法分别搭配 bool operator = = (const Key &x,const Key &y);
第一种完成从Record到Key的自动转换,注意the_key函数是在Record里的,即两个class里都要有这个函数。
第二种调用Key()构造临时Key tmp,比较后,调用析构函数释放tmp。注意一定要return,否则会内存泄漏。
- List父类里的insert,error判断条件是position > count,而其他函数都是 position >= count。>写错会导致读不进去列表。