学习了数据结构第一章的顺序表后,实验要求是使用顺序表存储数据,实现n人过桥问题,代码如下。
首先是顺序表的简单定义
const int incresize = 10; //数组满时,每次增加10个空间
struct Node {
char name[10]; //姓名
int time; //耗时
};
class SeqList {
private:
int maxsize = 10; //初始默认最大长度为10
Node* people; //动态申请内存空间的首地址
int length = 0; //元素个数
public:
SeqList(); //无参构造函数
SeqList(const Node a[], int n); //有参构造函数
~SeqList(); //析构函数
void setSeqList(const Node a[], int n); //设置函数
int getlength(); //返回顺序表长度
int getby_value(const Node a); //按值查找
void getby_order(int i); //按号查找
void insert(const Node person, int i); //插入函数
void Delete(int i); //删除函数
bool isempty(); //判断是否为空
void printdata(); //打印信息
void sort(); //根据耗时升序排序
int result(); //输出耗时最短结果
};
其次是顺序表的简单实现
#include <iostream>
using std::cout;
using std::endl;
#include "SeqList.h"
SeqList::SeqList() {
people = new Node[maxsize]; //默认大小10
length = 0;
}
SeqList::SeqList(const Node a[], int n) {
people = new Node[2 * n]; //长度设为2n
for (int i = 0; i < n; i++)
people[i] = a[i];
length = n;
maxsize = 2 * n; //最大长度变为2n
}
SeqList::~SeqList() {
delete[] people;
}
void SeqList::setSeqList(const Node a[], int n) {
Node* oldarray = people;
people = new Node[2 * n];
for (int i = 0; i < n; i++)
people[i] = a[i];
length = n;
maxsize = 2 * n;
delete oldarray;
}
int SeqList::getlength() {
return length;
}
bool SeqList::isempty() {
return (length == 0); //length==0返回真,否则返回假
}
void SeqList::printdata() {
if (isempty()) {
cout << "无数据" << endl;
return;
}
for (int i = 0; i < length; i++)
cout << people[i].name << "用时" << people[i].time << endl;
}
int SeqList::getby_value(const Node a){
if (isempty())
throw 1;
for (int i = 0; i < length; i++)
if (a.name == people[i].name && a.time == people[i].time) {
cout << people[i].name << "用时" << people[i].time << "在表中第" << i + 1 << "个位置" << endl;
return i+1;
}
throw 2;
}
void SeqList::getby_order(int i) {
if (i<0 || i>length)
throw 1;
cout << people[i-1].name << "用时" << people[i-1].time << "在表中第" << i << "个位置" << endl;
}
void SeqList::insert(const Node person, int i) {
if (i<1 || i > length)
throw 1;
if (i == maxsize) { //数组满时
Node* oldarray = people;
maxsize += incresize;
people = new Node[maxsize];
for (int j = 0; j < length; j++)
people[j] = oldarray[j];
people[length++] = person; //插入后length++
delete[] oldarray;
return;
}
for (int j = length; j >= i; j--) //数组不满时
people[j] = people[j - 1];
people[i - 1] = person;
length++;
}
void SeqList::sort() {
Node temp; //用于交换
for (int i = 0; i < length; i++)
for (int j = 0; j < length - 1; j++)
if (people[j].time > people[j + 1].time) {
temp = people[j];
people[j] = people[j + 1];
people[j + 1] = temp;
}
}
void SeqList::Delete(int i) {
if (i<1 || i > length)
throw 1;
for (int j = i; j < length; j++)
people[j - 1] = people[j];
length--;
}
然后是解决n人过桥问题的函数
核心思路是贪心,用递归实现。
首先依据过桥耗时进行排序。并且必须遵循以下两个原则:
- 同时过桥的两人必须相邻,以减少浪费的时间
- 每次让对岸耗时最短的人回来
具体步骤如下:
1)先让最快的两人过桥
2)让最慢的两人过桥
3)循环
可以保证每次回来都是最快的两人,耗时最短。代码如下:
int SeqList::result() {
int fin_time = 0; //最终用时
int rest = length; //没过桥的人
if (rest == 1)
return people[0].time;
sort(); //排序
while (rest != 0) {
fin_time += people[1].time; //最快两人过桥
cout << people[0].name << "和" << people[1].name << "过桥,用时" << people[1].time << endl;
rest -= 2;
if (rest == 0)
return fin_time;
fin_time += people[0].time; //岸对面最快的人回来
cout << people[0].name << "回来,用时" << people[0].time << endl;
rest++;
fin_time += people[rest].time; //最慢两人过桥
cout << people[rest-1].name << "和" << people[rest].name << "过桥,用时" << people[rest].time << endl;
rest -= 2; //过2个人
if (rest == 0)
return fin_time;
fin_time += people[1].time; //岸对面最快的人回来
cout << people[1].name << "回来,用时" << people[1].time << endl;
rest++; //回来一个
}
return fin_time;
}
最后是测试代码
#include<iostream>
#include <windows.h>
#include "SeqList.h"
using std::cout;
using std::cin;
using std::endl;
void printmenu();
int main() {
int n; //输入过桥人数
SeqList s1;
if (s1.isempty()) {
cout << "顺序表目前为空,请输入数据,有几人过桥?" << endl;
cin >> n;
Node* array = new Node[n]; //创建节点数组
cout << "依次输入过桥人的名字和其过桥用时:" << endl;
for (int i = 0; i < n; i++) {
cin >> array[i].name;
cin >> array[i].time;
}
s1.setSeqList(array,n);
}
cout << "当前有" << s1.getlength() << "人过桥" << endl;
s1.printdata();
system("pause");
int choice = 1; //选择功能
while (choice != 0) {
printmenu();
cin >> choice;
switch (choice) {
case 0:
exit(0);
case 1:
Node newpeople;
cout << "依次输出添加人的名字和过桥用时" << endl;
cin >> newpeople.name >> newpeople.time;
try {
s1.insert(newpeople, 1);
}
catch (int) {
cout << "插入位置错误,该顺序表共有" << s1.getlength() << "个人" << endl;
};
cout << "添加后信息为:" << endl;
s1.printdata();
system("pause");
break;
case 2:
s1.printdata();
cout << "输入要去掉人的序号:" << endl;
int num;
cin >> num;
try {
s1.Delete(num);
}
catch (int) {
cout << "删除位置错误,该顺序表共有" << s1.getlength() << "个人" << endl;
}
cout << "删除后信息为:" << endl;
s1.printdata();
system("pause");
break;
case 3:
Node temp;
cout << "依次输出要查找人的名字和过桥用时" << endl;
cin >> temp.name >> temp.time;
try {
s1.getby_value(temp);
}
catch (int e) {
if (e == 1)
cout << "未储存数据" << endl;
if (e == 2)
cout << "未找到" << endl;
}
system("pause");
break;
case 4:
cout << "输入查找表中第几个人" << endl;
cin >> num;
try {
s1.getby_order(num);
}
catch (int) {
cout << "查找序号错误,该顺序表共有" << s1.getlength() << "个人" << endl;
}
system("pause");
break;
case 5:
s1.sort();
cout << "排序后信息为:" << endl;
//此处没有break,排序后输出信息
case 6:
s1.printdata();
system("pause");
break;
case 7:
cout << "共用时" << s1.result() << endl;
system("pause");
break;
default:
cout << "请输入有效序号" << endl;
system("pause");
}
}
return 0;
}
void printmenu() {
system("cls");
cout << "1)添加一个人\t\t\t\t2)去掉一个人\n" <<
"3)根据信息查找一个人\t\t\t4)根据序号查找一个人\n" <<
"5)对过桥的人根据用时排序\t\t6)输出信息\n" <<
"7)输出答案\n" << endl;
cout << "输入对应的序号选择功能,输入0退出程序" << endl;
}