山东大学数据结构与算法实验4链式描述线性表(链表实验/链表合并)

A : 链表实现

题目描述

要求

1.封装链表类,链表迭代器类;

2.链表类需提供操作:在指定位置插入元素,删除指定元素,搜索链表中是否有指定元素,原地逆置链表,输出链表;

3.不得使用与链表实现相关的STL。

描述

第一行两个整数 N 和 Q。
第二行 N 个整数,作为节点的元素值,创建链表。
接下来 Q 行,执行各个操作,具体格式如下:

  • 插入操作 : 1 idx val,在链表的 idx 位置插入元素 val;
  • 删除操作 : 2 val,删除链表中的 val 元素。若链表中存在多个该元素,仅删除第一个。若该元素不存在,输出 -1
  • 逆置操作 : 3,原地逆置链表;
  • 查询操作 : 4 val,查询链表中的 val 元素,并输出其索引。若链表中存在多个该元素,仅输出第一个的索引。若不存在该元素,输出 -1
  • 输出操作 : 5,使用 链表迭代器 ,输出当前链表索引与元素的异或和

数据结构与算法描述

设置一个节点的结构体包括元素和下一节点的指针。私有成员节点个数、和指向链表第一个节点的指针。

template<class T>
struct chainNode {
	T element;//节点的元素
	chainNode<T> *next;//指向下一节点的指针
	chainNode(){}
	chainNode(const T& element, chainNode<T>* next) {
		this->element = element;
		this->next = next;
	}
};
template<class T>
class chain {
public:
	chain() {
		listsize = 0;
		firstNode = NULL;
	}
	void insert(int idx, const T& val);
	void erase(const T& val);
	void reverse();
	void seek(const T& val);
	void xora();
	class iterator {
	public:
		iterator(chainNode<T>* theNode=NULL) { node = theNode; }
		T& operator*() const { return node->element; }//提取元素
		iterator& operator++() {//前加
			node = node->next;
			return *this;
		}
		iterator operator++(int) {//后加
			iterator old;
			old = *this;
			node = node->next;
			return old;
		}
		bool operator!=(const iterator right)const {
			return node != right.node;
		}
		bool operator==(const iterator right)const {
			return node == right.node;
		}
	protected:
		chainNode<T>* node;
	};
	iterator begin() { return iterator(firstNode); }//第一个节点
	iterator end() { return iterator(NULL); }//NULL
private:
	int listsize;//节点个数
	chainNode<T>* firstNode;//指向链表第一个节点的指针
};

插入函数:如果索引为0,插在第一个直接调用new chainNode<T>(val,firstNode);如果不为0,则用for循环找到要索引节点的前一个节点然后查到它后面。

template<class T>
void chain<T>::insert(int idx, const T& val) {//插入
	if (idx == 0) {//如果索引为0,则插入到第一个节点
		firstNode=new chainNode<T>(val,firstNode); 
	}
	else {
		chainNode<T>* p=firstNode;
		for (int i = 0; i < idx-1 ; i++) {//找到索引节点的前一个节点p
			p = p->next;
		}
		p->next = new chainNode<T>(val, p->next);//插入到p的后面
	}
	listsize++;//节点数加一
}

删除函数:用for循环找到要删除的元素所在的位置。若存在则delete。

template<class T>
void chain<T>::erase(const T& val) {//删除给元素节点
	chainNode<T>* deleteNode = firstNode;
	while (deleteNode != NULL && deleteNode->element != val) {//找到要删除的元素所在的节点
		deleteNode = deleteNode->next;
	}
	if (deleteNode == NULL) {//没找到相等的元素
		cout << -1 << endl;
	}
	else {//找到
		listsize--;//节点数减一
		delete deleteNode;
	}
}

逆置函数:设置p,q两个节点q在后,在while循环中每次使q指向p,并设置一个节点q2,方便p,q向下一个节点移动。要注意q2到最后的next为NULL的情况。最后要改变原来的第一个节点的next为NULL,firstNode改为此时的最后一个节点。

template<class T>
void chain<T>::reverse() {//逆置
	chainNode<T>* p = firstNode;
	chainNode<T>* q = p->next;
	chainNode<T>* q2 = q->next;//该节点的目的时方便p和q向后移动
	while (q != NULL) {
		if (q2 != NULL) {
			q->next = p;//next指向前一个结点
			//p,q,q2向后移动一个节点
			p = q;
			q = q2;
			q2 = q2->next;
		}
		else {//q2已经是NULL了不用再指向下一个了
			q->next = p;
			p = q;
			q = q2;
		}
	}
	//改变第一个节点
	firstNode->next = NULL;
	firstNode = p;
}

查询函数:用for循环根据元素找到索引。

template<class T>
void chain<T>::seek(const T& val) {//查询元素
	chainNode<T>* seekNode = firstNode;
	int idx = 0;
	while (seekNode != NULL && seekNode->element != val) {//找到索引和该元素的节点
		seekNode = seekNode->next;
		idx++;
	}
	if (seekNode == NULL) {//没找到
		cout << -1 << endl;
	}
	else {//找到
		cout << idx << endl;
	}
}

迭代类:用一个构造函数,对节点node初始化。然后重载前加、后加、等于和不等于符号。重载*提取该节点的元素。之后要给链表类加一个begin和end函数。

输出异或和的函数:利用idx初始化为0作为索引方便求异或和。

template<class T>
void chain<T>::xora() {//输出异或和
	int idx = 0;//索引
	int result = 0;
	for (iterator i = begin(); i != end(); i++) {
		result += idx ^ (*i);//异或和
		idx++;
	}
	cout << result << endl;
}

测试输入输出

完整代码(含注释)

#include<iostream>
using namespace std;
template<class T>
struct chainNode {
	T element;//节点的元素
	chainNode<T> *next;//指向下一节点的指针
	chainNode(){}
	chainNode(const T& element, chainNode<T>* next) {
		this->element = element;
		this->next = next;
	}
};
template<class T>
class chain {
public:
	chain() {
		listsize = 0;
		firstNode = NULL;
	}
	void insert(int idx, const T& val);
	void erase(const T& val);
	void reverse();
	void seek(const T& val);
	void xora();
	class iterator {
	public:
		iterator(chainNode<T>* theNode=NULL) { node = theNode; }
		T& operator*() const { return node->element; }//提取元素
		iterator& operator++() {//前加
			node = node->next;
			return *this;
		}
		iterator operator++(int) {//后加
			iterator old;
			old = *this;
			node = node->next;
			return old;
		}
		bool operator!=(const iterator right)const {
			return node != right.node;
		}
		bool operator==(const iterator right)const {
			return node == right.node;
		}
	protected:
		chainNode<T>* node;
	};
	iterator begin() { return iterator(firstNode); }//第一个节点
	iterator end() { return iterator(NULL); }//NULL
private:
	int listsize;//节点个数
	chainNode<T>* firstNode;//指向链表第一个节点的指针
};
template<class T>
void chain<T>::insert(int idx, const T& val) {//插入
	if (idx == 0) {//如果索引为0,则插入到第一个节点
		firstNode=new chainNode<T>(val,firstNode); 
	}
	else {
		chainNode<T>* p=firstNode;
		for (int i = 0; i < idx-1 ; i++) {//找到索引节点的前一个节点p
			p = p->next;
		}
		p->next = new chainNode<T>(val, p->next);//插入到p的后面
	}
	listsize++;//节点数加一
}
template<class T>
void chain<T>::erase(const T& val) {//删除给元素节点
	chainNode<T>* deleteNode = firstNode;
	while (deleteNode != NULL && deleteNode->element != val) {//找到要删除的元素所在的节点
		deleteNode = deleteNode->next;
	}
	if (deleteNode == NULL) {//没找到相等的元素
		cout << -1 << endl;
	}
	else {//找到
		listsize--;//节点数减一
		delete deleteNode;
	}
}
template<class T>
void chain<T>::reverse() {//逆置
	chainNode<T>* p = firstNode;
	chainNode<T>* q = p->next;
	chainNode<T>* q2 = q->next;//该节点的目的时方便p和q向后移动
	while (q != NULL) {
		if (q2 != NULL) {
			q->next = p;//next指向前一个结点
			//p,q,q2向后移动一个节点
			p = q;
			q = q2;
			q2 = q2->next;
		}
		else {//q2已经是NULL了不用再指向下一个了
			q->next = p;
			p = q;
			q = q2;
		}
	}
	//改变第一个节点
	firstNode->next = NULL;
	firstNode = p;
}
template<class T>
void chain<T>::seek(const T& val) {//查询元素
	chainNode<T>* seekNode = firstNode;
	int idx = 0;
	while (seekNode != NULL && seekNode->element != val) {//找到索引和该元素的节点
		seekNode = seekNode->next;
		idx++;
	}
	if (seekNode == NULL) {//没找到
		cout << -1 << endl;
	}
	else {//找到
		cout << idx << endl;
	}
}
template<class T>
void chain<T>::xora() {//输出异或和
	int idx = 0;//索引
	int result = 0;
	for (iterator i = begin(); i != end(); i++) {
		result += idx ^ (*i);//异或和
		idx++;
	}
	cout << result << endl;
}
int main() {
	int n, q;
	cin >> n >> q;
	chain<int> c;
	for (int i = 0; i < n; i++) {
		int val;
		cin >> val;
		c.insert(i, val);
	}
	for (int i = 0; i < q; i++) {
		int x;
		cin >> x;
		if (x == 1) {
			int idx, val;
			cin >> idx >> val;
			c.insert(idx, val);
		}
		else if (x == 2) {
			int val;
			cin >> val;
			c.erase(val);
		}
		else if (x == 3) {
			c.reverse();
		}
		else if (x == 4) {
			int val;
			cin >> val;
			c.seek(val);
		}
		else if (x == 5) {
			c.xora();
		}
	}
}

B : 链表合并 

题目描述

要求

  1. 使用题目 链表实现 中实现的链表类、迭代器类完成本题
  2. 不得使用与题目实现相关的 STL

描述

给定两组整数序列,你需要分别创建两个有序链表,使用链表迭代器实现链表的合并,并分别输出这三个有序链表的索引与元素的异或和。

Note: 给定序列是无序的,你需要首先得到一个有序的链表

 数据结构与算法描述

排序函数:利用冒泡排序对链表中的元素重新排序。

template<class T>
void chain<T>::sort() {//冒泡排序
	for (int n = listsize; n > 1  ; n--) {
		chainNode<T>* p = firstNode;
		chainNode<T>* q = p->next;//p之后的一个节点
		for(int i=0;i<n-1;i++){
			if (p->element > q->element) {//交换
				T t;
				t= p->element;
				p->element = q->element;
				q->element = t;
			}
			p = p->next;//p,q向后一个节点
			q = q->next;
		}
	}
}

链表合并:依次比较第一个链表和第二个链表元素的大小,小的先查输入到第三个数组中,利用迭代器插入一个之后插入的那个++,等到其中一个完全插入之后,有剩余的那个链表在将剩余的全部插入第三个链表中。

int main() {
	int n, m;
	cin >> n >> m;
	chain<int> c1;
	for (int i = 0; i < n; i++) {
		int val;
		cin >> val;
		c1.insert(i, val);
	}
	chain<int> c2;
	for (int i = 0; i < m; i++) {
		int val;
		cin >> val;
		c2.insert(i, val);
	}
	c1.sort();//排序
	c2.sort();
	chain<int> c3;
	chain<int>::iterator c1b = c1.begin();
	chain<int>::iterator c2b = c2.begin();
	int i = 0;
	while (c1b != c1.end() && c2b != c2.end()) {
		if ((*c1b) > (*c2b)) {//将较小的插入
			c3.insert(i, (*c2b));
			i++;
			c2b++;
		}
		else {
			c3.insert(i, (*c1b));
			i++;
			c1b++;
		}
	}
	//将剩余的插入
	while (c1b != c1.end()) {
		c3.insert(i, (*c1b));
		i++;
		c1b++;
	}
	while (c2b != c2.end()) {
		c3.insert(i, (*c2b));
		i++;
		c2b++;
	}
	c1.xora();
	c2.xora();
	c3.xora();
	return 0;
}

测试输入输出

完整代码(含注释)

#include<iostream>
using namespace std;
template<class T>
struct chainNode {
	T element;//节点的元素
	chainNode<T>* next;//指向下一节点的指针
	chainNode() {}
	chainNode(const T& element) { this->element = element; }
	chainNode(const T& element, chainNode<T>* next) {
		this->element = element;
		this->next = next;
	}
};
template<class T>
class chain {
public:
	chain() {
		listsize = 0;
		firstNode = NULL;
	}
	void insert(int idx, const T& val);
	void erase(const T& val);
	void reverse();
	void seek(const T& val);
	void xora();
	void sort();
	class iterator {
	public:
		iterator(chainNode<T>* theNode = NULL) { node = theNode; }
		T& operator*() const { return node->element; }//提取元素
		iterator& operator++() {//前加
			node = node->next;
			return *this;
		}
		iterator operator++(int) {//后加
			iterator old;
			old = *this;
			node = node->next;
			return old;
		}
		bool operator!=(const iterator right)const {
			return node != right.node;
		}
		bool operator==(const iterator right)const {
			return node == right.node;
		}
	protected:
		chainNode<T>* node;
	};
	iterator begin() { return iterator(firstNode); }//第一个节点
	iterator end() { return iterator(NULL); }//NULL
private:
	int listsize;//节点个数
	chainNode<T>* firstNode;//指向链表第一个节点的指针
};
template<class T>
void chain<T>::insert(int idx, const T& val) {
	if (idx == 0) {
		firstNode = new chainNode<T>(val, firstNode);
	}
	else {
		chainNode<T>* p = firstNode;
		for (int i = 0; i < idx - 1; i++) {
			p = p->next;
		}
		p->next = new chainNode<T>(val, p->next);
	}
	listsize++;
}
template<class T>
void chain<T>::erase(const T& val) {
	chainNode<T>* deleteNode = firstNode;
	while (deleteNode != NULL && deleteNode->element != val) {
		deleteNode = deleteNode->next;
	}
	if (deleteNode == NULL) {
		cout << -1 << endl;
	}
	else {
		listsize--;
		delete deleteNode;
	}
}
template<class T>
void chain<T>::reverse() {
	chainNode<T>* p = firstNode;
	chainNode<T>* q = p->next;
	chainNode<T>* q2 = q->next;
	while (q != NULL) {
		if (q2 != NULL) {
			q->next = p;
			p = q;
			q = q2;
			q2 = q2->next;
		}
		else {
			q->next = p;
			p = q;
			q = q2;
		}
	}
	firstNode->next = NULL;
	firstNode = p;
}
template<class T>
void chain<T>::seek(const T& val) {
	chainNode<T>* seekNode = firstNode;
	int idx = 0;
	while (seekNode != NULL && seekNode->element != val) {
		seekNode = seekNode->next;
		idx++;
	}
	if (seekNode == NULL) {
		cout << -1 << endl;
	}
	else {
		cout << idx << endl;
	}
}
template<class T>
void chain<T>::xora() {
	int idx = 0;
	int result = 0;
	for (iterator i = begin(); i != end(); i++) {
		result += idx ^ (*i);
		idx++;
	}
	cout << result << endl;
}
template<class T>
void chain<T>::sort() {//冒泡排序
	for (int n = listsize; n > 1  ; n--) {
		chainNode<T>* p = firstNode;
		chainNode<T>* q = p->next;//p之后的一个节点
		for(int i=0;i<n-1;i++){
			if (p->element > q->element) {//交换
				T t;
				t= p->element;
				p->element = q->element;
				q->element = t;
			}
			p = p->next;//p,q向后一个节点
			q = q->next;
		}
	}
}
int main() {
	int n, m;
	cin >> n >> m;
	chain<int> c1;
	for (int i = 0; i < n; i++) {
		int val;
		cin >> val;
		c1.insert(i, val);
	}
	chain<int> c2;
	for (int i = 0; i < m; i++) {
		int val;
		cin >> val;
		c2.insert(i, val);
	}
	c1.sort();//排序
	c2.sort();
	chain<int> c3;
	chain<int>::iterator c1b = c1.begin();
	chain<int>::iterator c2b = c2.begin();
	int i = 0;
	while (c1b != c1.end() && c2b != c2.end()) {
		if ((*c1b) > (*c2b)) {//将较小的插入
			c3.insert(i, (*c2b));
			i++;
			c2b++;
		}
		else {
			c3.insert(i, (*c1b));
			i++;
			c1b++;
		}
	}
	//将剩余的插入
	while (c1b != c1.end()) {
		c3.insert(i, (*c1b));
		i++;
		c1b++;
	}
	while (c2b != c2.end()) {
		c3.insert(i, (*c2b));
		i++;
		c2b++;
	}
	c1.xora();
	c2.xora();
	c3.xora();
	return 0;
}

如能打赏,不胜感激[叩谢]。

  • 22
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值