引入Key類。
Key類指要查找的數據中最關鍵最有標識性的部分,查找時通過key的比較,快速判斷出這個數據是否是要查找的數據。
#include<iostream>
using namespace std;
class Key
{
int key; //數據中的關鍵部分,有辨識度
public:
//static int comparisons; //比較次數
Key (int x = 0);
int the_key() const;
};
//int Key::comparisons = 0;
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 Key &x,const Key &y); //"!="運算符重載
Key::Key(int x)
{
key = x;
}
int Key::the_key() const
{
return key;
}
bool operator == (const Key &x, const Key &y)
{
//Key::comparisons++;
return x.the_key() == y.the_key();
}
bool operator > (const Key &x, const Key &y)
{
//Key::comparisons++;
return x.the_key() > y.the_key();
}
bool operator < (const Key &x, const Key &y)
{
//Key::comparisons++;
return x.the_key() < y.the_key();
}
bool operator >= (const Key &x, const Key &y)
{
//Key::comparisons++;
return x.the_key() >= y.the_key();
}
bool operator <= (const Key &x, const Key &y)
{
//Key::comparisons++;
return x.the_key() <= y.the_key();
}
bool operator != (const Key &x, const Key &y)
{
//Key::comparisons++;
return x.the_key() != y.the_key();
}
一.順序查找(待查找的線性表已經是一個有序線性表)
- 查找有順序的線性表,從線性表的第一項開始,逐個進行比較。
#include "list.cpp"
#include "key.cpp"
typedef Key Record;
Error_code sequential_search(const List<Record> &the_list,const Key &target,int &position) //the_list引用提供的線性表,target引用數據中的關鍵部分,如果查找到將其位置賦給position
{
int s = the_list.size(); //線性表大小
for(position = 0;position < s;position++) //遍歷
{
Record data;
the_list.retrieve(position,data); //將當前位置中存儲的數據賦給data
if(data == target) return success; //如果data是要查找的數據,則查找成功,position正好是其位置
}
return not_present; //如果遍歷完仍未找到,說明該線性表中沒有這個數據
}
2.2. 查找有順序的線性表。加入一個哨兵,先將要查找的這一項插入表的末尾,這樣遍歷表時一定能找到一個正確位置,只需判斷所得的位置是否是最後一個位置即可。省去了判斷位置信息,不用擔心查找超界。
#include "list.cpp"
#include "key.cpp"
typedef Key Record;
Error_code sequential_search(List<Record> &the_list,const Key &target,int &position) //the_list引用提供的線性表,target引用數據中的關鍵部分,如果查找到將其位置賦給position
{
Record data;
int s = the_list.size(); //線性表大小
the_list.insert(s,target); //將要查找的數據插入表的末尾
for(position = 0;;position++) //遍歷
{
the_list.retrieve(position,data); //將當前位置中存儲的數據賦給data
if(data == target) break;//如果data是要查找的數據,則跳出
}
the_list.remove(s,data); //刪除插入的數據
if(position < s) return success; //如果position不是最後一項,則成功,position正好是其位置
return not_present;//如果遍歷完仍未找到,說明該線性表中沒有這個數據
}
二.插半查找
引出 Orlist類.
將數據有順序的插入表中,要重載insert函數,覆蓋insert,replace函數。
#include "key.cpp"
#include "list.cpp"
typedef Key Record;
class Ordered_list:public List<Record>
{
public:
Ordered_list(); //構造函數
Error_code insert(const Record &data); //只傳入要插入的數據,由程序找合適的位置插入
Error_code insert(int position, const Record &data); //傳入要插入的數據和指定位置,如果數據在該位置合適則插入,不合適則不插入,返回相應信息
Error_code replace(int position, const Record &data);//傳入要替換的數據和指定位置,如果數據在該位置合適則替換,不合適則不替換,返回相應信息
};
Ordered_list::Ordered_list() //構造函數
{}
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<Record>::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<Record>::insert(position, data); //將新的數據插入這個位置,這個位置原本的數據向後移一位
}
Error_code Ordered_list::replace(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()-1) //判斷指定位置是否越界
{
retrieve(position+1, list_data);//返回下一個位置的數據
if (data > list_data)//判斷,要替換的數據應該小於等於下一個位置的數據
return fail;//如果要替換的數據小於下一個位置的數據,則不能替換
}
return List<Record>::replace(position, data); //替換這個位置的數據
}
1.將要查找的數據先與線性表的中間位置做比較,如果小於中間位置則說明要找的元素在後半部分,然後繼續折半查找後半部分;如果小於中間位置則說明要找的元素在前半部分,然後繼續折半查找前半部分。直到前後指針指向同一個元素,判斷是否是要查找的元素。
#include<iostream>
#include "ordlist.cpp"
using namespace std;
Error_code recursive_binary_2(const Ordered_list &the_list, const Key &target,int bottom, int top, int &position)//傳入排好序的鏈表,關鍵字,當前前指針的位置,當前後指針的位置,如果查到了將位置賦給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_2(the_list, target, mid + 1, top, position); //遞歸,此時前指針移到中間位置的後一個位置
else //如果中間的值大於要查找的值,說明要查找的值在前半部分
return recursive_binary_2(the_list, target, bottom, mid - 1, position); //遞歸,後指針移到中間位置的前一個位置
}
else return not_present;
}
Error_code run_recursive_binary_2(const Ordered_list &the_list,const Key &target, int &position)
{
return recursive_binary_2(the_list, target, 0, the_list.size() - 1, position); //給遞歸函數傳入初始值
}
2.要找到該數第一次出現的位置,我們只能在找出一個正確位置時先將它保存起來,這樣最後前後指針指向同一個元素時,如果是要查找的數據則一定是第一個。
#include<iostream>
#include "ordlist.cpp"
using namespace std;
Error_code recursive_binary_1(const Ordered_list &the_list, const Key &target,int bottom, int top, int &position)//傳入排好序的鏈表,關鍵字,如果查到了將位置賦給position
{
Record data;
if (bottom < top) //當前指針小於後指針
{
int mid = (bottom + top) / 2;//找出中間座標
the_list.retrieve(mid, data);//返回中間座標的值
if (data < target) //如果中間的值小於要查找的值,說明要查找的值在後半部分
return recursive_binary_1(the_list, target, mid + 1, top, position);//遞歸,前指針移到中間位置的後一個位置
else //如果中間的值大於要查找的值,說明要查找的值在前半部分
return recursive_binary_1(the_list, target, bottom, mid, position); //遞歸,後指針移到中間位置
}
else if (top < bottom)
return not_present; //當前指針大於後指針時,說明沒有找到
else { //當前後指針指向同一個元素時
position = bottom;//將這個位置賦給position
the_list.retrieve(bottom, data);//取出這個位置的值
if (data == target) return success;//如果這個位置的值等於要查找的值,則該位置一定是在這個表中第一次出現的位置
else return not_present;//如果不是則說明表中沒有這個數據
}
}
Error_code run_recursive_binary_1(const Ordered_list &the_list,const Key &target, int &position)
{
return recursive_binary_1(the_list, target, 0, the_list.size() - 1, position); //將初始值傳給遞歸函數
}