C++折中查找
自学
- 例题:假设学生记录文件 students.dat 是按照姓名排好序的,编写程序,在 students.dat 文件中用折半查找的方法找到姓名为 Jack 的学生记录,并将其年龄改为 20(假设文件很大,无法全部读入内存)
程序如下:
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
class CStudent
{
public:
char szName[20];
int age;
};
void getName( CStudent s)
{
ofstream outFile("student.dat", ios::out | ios::binary);
if (!outFile) //需要对是否打开文件进行必要判断,避免error
{ cout<<"Open and write "student.dat" failed"<<endl;
return 0;
}
cout<<"Please input students' name and age:"<<endl;
while(cin >> s.szName >> s.age) //单个进行读取
{
int flag = strcmp(s.szName,"finish");
if(flag == 0) //判断是否完成输入
break;
else
{
outFile.write((char*)&s, sizeof(s));
cout<<"已经读取"<<s.szName<<" "<<s.age<<endl;
}
outFile.close; //关闭打开的文件
}
void main()
{
CStudent s;
getName( CStudent s); //写入文件
fstream ioFile("Student.dat", ios::in | ios::out); //用二进制读写的方法打开文件
if (!ioFile) //手动判断文件是否打开
{
cout<<"Error!!!"<<endl;
return 0;
}
/*要获取文件长度,可以用 seekg 函数将文件读指针定位到文件尾部,再用 tellg 函数获取文 件读指针的位置,此位置即为文件长度*/
ioFile.seekg(0,ios::endl);
int L = 0,R; //L是折中查找的第一个序号,R是最后一个
R = ioFile.tellg() / sizeof(CStudent) -1; //首次查找法范围的最后一个记录的序号就是:记录总数-1
do{
int mid = (L+R) / 2;
ioFile.seekg(mid*sizeof(CStudent),ios::beg); //指针定位到中间位置
ioFile.read((char *)&s,sizeof(s)); //读取数据
int tmp = strcmp(s.szName, "Jack");
if (tmp ==0) //找到了
{
cout<<"修改之前:"<<s.szName<<" "<<s.age<<endl;
s.age = 20;
ioFile.seekg(mid*sizeof(CStudent),ios::beg);
ioFile.write((char*)&s,sizeof(s));
cout<<"修改之后"<<s.szName<<" "<<s.age<<endl;
break;
}
else if(tmp >0) //前一半查找
R = mid -1;
else //后一半查找
L = mid +1;
}while(L<=R);
ioFile.close();
return 0;
}