实验02 链表2022

. 【程序填空】单链表类定义

时间限制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;
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值