. 【程序填空】单链表类定义
时间限制1s
内存限制128MB
题目描述
已知带头结点的单链表的类界面和部分函数定义
请根据主函数的要求,完成单链表类的其他函数填空
输入
第1行先输入n表示有n个数据,接着输入n个数据
第2行输入要插入的位置和新数据
第3行输入要插入的位置和新数据
第4行输入要删除的位置
第5行输入要删除的位置
第6行输入要查找的位置
第7行输入要查找的位置
输出
数据之间用空格隔开
第1行输出创建后的单链表内容
接着每一次操作后,如果操作成功则输出整个单链表内容,如果操作失败(包括插入、删除、查找等失败),输出字符串error,不必输出表内容
输入:
5 1 2 3 4 5
6 666
9 99
1
6
1
0
输出:
1 2 3 4 5
1 2 3 4 5 666
error
2 3 4 5 666
error
2
error
#include <iostream>
using namespace std;
#define OK 0
#define ERROR -1
//结点类定义
class ListNode {
public:
int data;
ListNode* next;
ListNode()
{
data = -9999, next = NULL;
}
ListNode(int item, ListNode* pt)
{
data = item, next = pt;
}
};
class LinkList {
//带头结点的单链表,位置从0到n,0是头结点,1是首结点,n是尾结点
private:
ListNode* head; //头结点
int size; //表长
ListNode* index(int i); //定位函数,返回第i个结点
public:
LinkList(); //构造函数,创建头结点
~LinkList(); //析构函数,逐个结点回收
int LL_insert(int item, int i); //第i位置插入元素,操作成功或失败返回OK或ERROR
int LL_del(int i); //删除第i位置的元素,操作成功或失败返回OK或ERROR
int LL_get(int i); //获取位置i的元素的数值,查找成功返回数值,查找失败返回ERROR
void LL_print(); //打印单链表所有数据
};
//提示:index函数可以不使用。如果不用要在填空区域定义一个空函数体保证语法正确性
LinkList::LinkList() : size(0)
{
head = new ListNode();
}
LinkList::~LinkList() //要逐个结点回收
{
ListNode* p, * q;
p = head->next;
while (p != NULL) {
q = p; p = p->next;
delete q;
}
size = 0;
head->next = NULL;
}
//以下完成其他类函数定义
/********** Write your code here! **********/
ListNode* LinkList:: index(int i) {
if (i <= 0 || i > size + 1) {
cout << "error" << endl;
return NULL;
}
ListNode* p = new ListNode;
p = head;
while (i--) p = p->next;
return p;
}
int LinkList::LL_insert(int item, int i) {
if (i > size + 1 || i <= 0) {
return ERROR;
}
size++;
ListNode* node = new ListNode;
node->data = item;
ListNode* p = new ListNode;
p = head;
while (--i)p = p->next;
node->next = p->next;
p->next = node;
return OK;
}
int LinkList::LL_del(int i) {
if (i > size || i <= 0) {
return ERROR;
}
size--;
ListNode* p = new ListNode;
p = head;
while (--i) p = p->next;
ListNode* q = p->next;
p->next = q->next;
delete q;
return OK;
}
int LinkList::LL_get(int i) {
if (i > size || i <= 0) {
return ERROR;
}
ListNode* p = new ListNode;
p = head;
while (i--)p = p->next;
return p->data;
}
void LinkList::LL_print() {
if (head->next==NULL) {
cout << "error" << endl;
return ;
}
ListNode* p = new ListNode;
p = head->next;
while (p->next) {
cout << p->data << " ";
p = p->next;
}
cout << p->data << endl;
return;
}
/*******************************************/
//主函数定义
int main()
{
int i, t, temp, pos;
LinkList sl; //创建单链表
//初始化链表
cin >> t; //输入初始长度
for (i = 1; i <= t; i++)
{
cin >> temp; sl.LL_insert(temp, i);
}
sl.LL_print();
//两次插入
for (i = 0; i < 2; i++)
{
cin >> pos >> temp;
t = sl.LL_insert(temp, pos);
if (t == ERROR) cout << "error" << endl;
else sl.LL_print();
}
//两次删除
for (i = 0; i < 2; i++)
{
cin >> pos;
t = sl.LL_del(pos);
if (t == ERROR) cout << "error" << endl;
else sl.LL_print();
}
//两次查找
for (i = 0; i < 2; i++)
{
cin >> pos;
t = sl.LL_get(pos);
if (t == ERROR) cout << "error" << endl;
else cout << t << endl;
}
return 0;
}
【id:33】【20分】B. DS单链表--结点交换
时间限制1s
内存限制128MB
题目描述
用C++实现含头结点的单链表,然后实现单链表的两个结点交换位置。
注意不能简单交换两个结点包含数据,必须通过修改指针来实现两个结点的位置交换
交换函数定义可以参考:
swap(int pa, int pb) //pa和pb表示两个结点在单链表的位置序号
swap (ListNode * p, ListNode * q) //p和q表示指向两个结点的指针
输入
第1行先输入n表示有n个数据,接着输入n个数据
第2行输入要交换的两个结点位置
第3行输入要交换的两个结点位置
输出
第一行输出单链表创建后的所有数据,数据之间用空格隔开
第二行输出执行第1次交换操作后的单链表数据,数据之间用空格隔开
第三行输出执行第2次交换操作后的单链表数据,数据之间用空格隔开
如果发现输入位置不合法,输出字符串error,不必输出单链表
输入:
5 11 22 33 44 55
1 4
2 6
输出:
11 22 33 44 55
44 22 33 11 55
error
#include<iostream>
using namespace std;
struct list {
int data;
list* next;
}*head;
void swap(list* p, list* q) {
list* pp = new list;
pp = head;
while (pp->next != p)pp = pp->next;
list* qq = new list;
qq = head;
while (qq->next != q)qq = qq->next;
list* ppp = new list;
ppp = p->next;
p->next = q->next;
qq->next = p;
pp->next = q;
q->next = ppp;
}
void print(list* head) {
list* p = head->next;
int n = head->data;
while (n--) {
cout << p->data << " ";
p = p->next;
}
cout << endl;
}
int main() {
int n, num, n1, n2;
cin >> n;
head = new list{ n,NULL };
list* p = head;
for (int i = 0; i < n; i++)
{
cin >> num;
list* node = new list{ num,NULL };
p->next = node;
p = p->next;
}
print(head);
for (int i = 0; i < 2; i++) {
cin >> n1 >> n2;
if (n1 > head->data || n2 > head->data || n1 <= 0 || n2 <= 0) {
cout << "error" << endl;
continue;
}
list* p1 = head;
list* p2 = head;
while (n1--)p1 = p1->next;
while (n2--)p2 = p2->next;
swap(p1, p2);
print(head);
}
}
【id:34】【20分】C. DS单链表--合并
时间限制1s
内存限制128MB
题目描述
假定两个单链表是递增有序,定义并实现以下函数,完成两个单链表的合并,继续保持递增有序
int LL_merge(ListNode *La, ListNode *Lb)
输入
第1行先输入n表示有n个数据,接着输入n个数据
第2行先输入m表示有M个数据,接着输入m个数据
输出
输出合并后的单链表数据,数据之间用空格隔开
输入:
3 11 33 55
4 22 44 66 88
输出:
11 22 33 44 55 66 88
#include<iostream>
using namespace std;
struct list {
int data;
list* next;
};//链表定义
void print(list* head) {//输出函数
list* p = head->next;
int n = head->data;
while (n--) {
cout << p->data << " ";
p = p->next;
}
cout << endl;
}
int LL_merge(list* la, list* lb) {
list* lc = la;
if (la->next->data > lb->next->data) {
lc = la;
la = lb;
lb = lc;
}//保证la指向的第一个数据小的链表
la->data += lb->data;//la作为结果链表,首先使它记录的链表长度增加(其实有错,懒得改)
list* p = lb->next;//p记录链表lb的结点
for (int i = 0; i < lb->data; i++) {
list* b = p;//b指针作为交换用的结点
p = p->next;
list* a = la->next;
while (1) {
if (a->next == NULL) break;//a是末尾或者b的数据介于a和a的下一元素的数据之间时,a指针记录的是b插入位置的前一结点
else if (a->data<=b->data && a->next->data>=b->data) break;//为了美观用了else if
else a = a->next;
}
b->next = a->next;
a->next = b;//插入结点b
}
//最后就是删去相同元素
p = la->next;
while (p->next) {
if (p->data == p->next->data)p->next = p->next->next;//如果p和它的下一个元素相同,直接让p的下下个元素成为p的后继结点
p = p->next;//原来中间的元素直接懒得理了,要删就再用一个指针指向它然后delete(怕代码太长了)
if (p == NULL) break;//这是我的写法问题,不加这句,编译不通过(因为p==NULL时while里面的p->next会报错)
}
print(la);
return 0;
}
int main() {
int n, m, a;
cin >> n;
list* la = new list{ n,NULL };
list* p = la;
for (int i = 0; i < n; i++)
{
cin >> a;
list* node = new list{ a,NULL };
p->next = node;
p = p->next;
}//创建链表la
cin >> m;
list* lb = new list{ m,NULL };
p = lb;
for (int i = 0; i < m; i++) {
cin >> a;
list* node =new list{ a,NULL };
p->next = node;
p = p->next;
}//创建链表lb
LL_merge(la, lb);
}
D. DS线性表—多项式相加
对于一元多项式p(x)=p0+p1x+p2x2+…+pnxn,每个项都有系数和指数两部分,例如p2x2的系数为p2,指数为2。
编程实现两个多项式的相加。
例如5+x+2x2+3x3,-5-x+6x2+4x4,两者相加结果:8x2+3x3+4x4
其中系数5和-5都是x的0次方的系数,相加后为0,所以不显示。x的1次方同理不显示。
要求用单链表实现。
输入
第1行:输入t表示有t组测试数据
第2行:输入n表示有第1组的第1个多项式包含n个项
第3行:输入第一项的系数和指数,以此类推输入n行
接着输入m表示第1组的第2个多项式包含m项
同理输入第2个多项式的m个项的系数和指数
参考上面输入第2组数据,以此类推输入t组
假设所有数据都是整数
输出
对于每1组数据,先用两行输出两个原来的多项式,再用一行输出运算结果,不必考虑结果全为0的情况
输出格式参考样本数据,格式要求包括:
1.如果指数或系数是负数,用小括号括起来。
2.如果系数为0,则该项不用输出。
3.如果指数不为0,则用符号^表示,例如x的3次方,表示为x^3。
4.多项式的每个项之间用符号+连接,每个+两边加1个空格隔开。
输入:
2
4
5 0
1 1
2 2
3 3
4
-5 0
-1 1
6 2
4 4
3
-3 0
-5 1
2 2
4
9 -1
2 0
3 1
-2 2
输出:
5 + 1x^1 + 2x^2 + 3x^3
(-5) + (-1)x^1 + 6x^2 + 4x^4
8x^2 + 3x^3 + 4x^4
(-3) + (-5)x^1 + 2x^2
9x^(-1) + 2 + 3x^1 + (-2)x^2
9x^(-1) + (-1) + (-2)x^1
#include<iostream>
using namespace std;
struct list{
int data;
int index;
list* next;
};
void out(int a) {
if (a < 0) cout << "(" << a << ")";
else if (a > 0) cout << a;
}
void initlist(list *head) {
int n;
cin >> n;
head->data = n;
head->index = -999;
list* p = head;
while (n--) {
int data, index;
cin >> data >> index;
list* node = new list{ data,index,NULL };
p->next = node;
p = p->next;
}
}
void print(list* head) {
list* p = head->next;
for (int i = 0; i < head->data - 1;i++) {
if (p->data == 0) {
p = p->next;
continue;
}
out(p->data);
if (p->index) {
cout << "x^";
out(p->index);
}
if (i != head->data - 1) cout << " + ";
p = p->next;
}
if (p->data!=0) {
out(p->data);
cout << "x^";
out(p->index);
}
cout << endl;
}
list* add(list* a, list* b) {
list* p = new list{ 999,-999,NULL };
p = a->next;
if (a->next->index > b->next->index) {
a ->next= b->next;
b->next = p;
}
list* q = b->next;
while(q) {
p = a->next;
list* node = q;
q = q->next;
while (p) {
if (p->index == node->index) {
p->data += node->data;
break;
}
else if (p->next == NULL) {
a->data++;
node->next = NULL;
p->next = node;
break;
}
else if (p->index<node->index && p->next->index>node->index) {
a->data++;
node->next = p->next;
p->next = node;
break;
}
p = p->next;
}
}
return a;
}
int main() {
int n;
cin >> n;
while (n--) {
list* a=new list, * b=new list;
initlist(a);
initlist(b);
print(a);
print(b);
list* c = add(a, b);
print(c);
}
}
E. DS链表—学生宿舍管理(双向列表容器List)
题目描述
假设某校有20间宿舍,宿舍编号101,102,...,120。每间只住一名学生。初始部分宿舍已用。用两个链表(已用宿舍链表和可用宿舍链表)维护宿舍的管理,实现宿舍分配、宿舍交回。
约定已用宿舍链表按宿舍号升序链接。初始可用宿舍链表也按宿舍号升序链接。
宿舍分配从可用宿舍链表中摘取第一间宿舍分配给学生。学生交回的宿舍挂在可用宿舍链表最后。
备注:使用list容器或静态链表。不用考虑宿舍分配和交回不成功的情况。
输入
初始宿舍状态,第一行输入n,表示已用宿舍n间
后跟n行数据,每行格式为:学生姓名 宿舍号
操作次数m,后跟m行操作,操作格式如下:
assign 学生 //为学生分配宿舍,从可用宿舍链表头摘取一间宿舍,
//按宿舍号升序挂在已用宿舍链表中。
return 宿舍号 //学生退宿舍,删除已用宿舍链表中对应结点,
//挂在可用宿舍链表尾部。
display_free //输出可用宿舍链表信息。
display_used //输出已用宿舍链表信息。
输出
display_free依次输出当前可用宿舍链表中的宿舍号,具体格式见样例。
display_used依次输出当前已用宿舍链表中的宿舍号,具体格式见样例
提示
list是一种序列式容器, list实际上就构成了一个双向循环链,
List类使用的参考代码
包含头文件<list> : #include <list>
List定义和初始化:
list<int>lst1; //创建空list
list<int> lst2(5); //创建含有5个元素的list
list<int>lst3(3,2); //创建含有3个元素的list
list<int>lst4(lst2); //使用lst2初始化lst4
list<int>lst5(lst2.begin(),lst2.end()); //同lst4
创建一个list对象l(注意list是模板类):list<char> l; //堆栈的数据类型是字符型
把一个字符ct添加到链表末尾: s.push_back(ct);
把一个字符ct插入到链表头部: s.push_front(ct);
获取链表第一个元素和最后一个元素:front()和back(),获取链表第一个元素,放入变量c2: c2 = s.front();
删除链表第一个元素和最后一个元素pop_front()和pop_back();
判断 判断list是否为空:empty(): l.empty(),如果为空则函数返回true,如果不空则返回false
begin() 返回指向第一个元素的迭代器
end() 返回末尾的迭代器
rbegin() 返回指向第一个元素的逆向迭代器
rend() 指向list末尾的逆向迭代器
程序示列:
#include <iostream>
using namespace std;
typedef list<int> LISTINT;
void main()
{
//用LISTINT创建一个list对象
LISTINT listOne;
//声明i为迭代器
LISTINT::iterator i;
listOne.push_front(3);
listOne.push_front(2);
listOne.push_front(1);
listOne.push_back(4);
listOne.push_back(5);
listOne.push_back(6);
cout << "listOne.begin()--- listOne.end():" << endl;
for (i = listOne.begin(); i != listOne.end(); ++i)
cout << *i << " ";
cout << endl; //正向输出
LISTINT::reverse_iterator ir;
cout << "listOne.rbegin()---listOne.rend():" << endl;
for (ir = listOne.rbegin(); ir != listOne.rend(); ir++) {
cout << *ir << " ";
}
cout << endl; //反向输出
}
输入:
5
李明 103
张三 106
王五 107
钱伟 112
章立 118
8
assign 李四
assign 赵六
return 118
return 101
assign 马山
display_used
assign 林立
display_free
输出:
赵六(102)-李明(103)-马山(104)-张三(106)-王五(107)-钱伟(112)
108-109-110-111-113-114-115-116-117-119-120-118-101
#include <iostream>
#include<list>
#include <algorithm>
using namespace std;
struct room {
string name;
int num;
bool operator< (const room& f) {//重载运算符,方便使用sort
if (f.num > this->num) {
return true;
}
return false;
}
};
list<room>have_been_used;
list<int>can_used;
int main() {
int n, num;
string name,s1,s2;
cin >> n;
for (int i = 101; i <= 120; i++) can_used.push_back(i);
while (n--) {
cin >> name >> num;
room r;
r.name = name;
r.num = num;
can_used.remove(num);
have_been_used.push_back(r);
}
have_been_used.sort();
cin >> n;
while (n--) {
cin >> s1;
if (s1 == "assign") {
cin >> name;
have_been_used.push_back({name, can_used.front()});
can_used.pop_front();
}
else if (s1 == "return") {
cin >> num;
for (list<room>::iterator i = have_been_used.begin(); i != have_been_used.end(); i++) {
if (i->num == num) {
have_been_used.erase(i);
break;
}
}
can_used.push_back(num);
}
else if (s1 == "display_used") {
have_been_used.sort();
for (list<room>::iterator i = have_been_used.begin(); i != have_been_used.end(); i++) {
if (i == have_been_used.begin()) cout << i->name << "(" << i->num << ")";
else cout <<"-" << i->name << "(" << i->num << ")";
}
cout << endl;
}
else if (s1 == "display_free") {
for (list<int>::iterator i = can_used.begin(); i !=can_used.end(); i++) {
if (i == can_used.begin()) cout << *i;
else cout << "-" << *i;
}
cout << endl;
}
}
}