山东大学数据结构与算法实验4链式描述线性表(链表实验/链表合并)
A:链表实现封装链表类,链表迭代器类链表类需提供操作:在指定位置插入元素,删除指定元素,搜索链表中是否有指定元素,原地逆置链表,输出链表不得使用与链表实现相关的 STL。B:链表合并使用题目 链表实现 中实现的链表类、迭代器类完成本题不得使用与题目实现相关的 STL给定两组整数序列,你需要分别创建两个有序链表,使用链表迭代器实现链表的合并,并分别输出这三个有序链表的索引与元素的异或和。注: 给定序
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 : 链表合并
题目描述
要求
- 使用题目 链表实现 中实现的链表类、迭代器类完成本题
- 不得使用与题目实现相关的 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;
}
如能打赏,不胜感激[叩谢]。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)