头文件
//
// Created by 23518 on 2020/10/25.
//
#ifndef TEST_EXPRIMENT3_MYLIST_H
#define TEST_EXPRIMENT3_MYLIST_H
#include <iostream>
using namespace std;
template<typename T = int>
class MyList {
private:
struct Node {
T data;
Node* prior = nullptr;
Node* next = nullptr;
};
Node LNode;
Node* front = &LNode;
Node* rear = &LNode;
int size_ = 0;
public:
MyList() = default;
MyList(const MyList<T>&);
MyList(const MyList<T>&&) = delete;
MyList& operator=(const MyList&);
MyList& operator=(const MyList&&) = delete;
~MyList();
T operator[](int index) const noexcept(false);
T& operator[](int index) noexcept(false);
void clear();
[[maybe_unused]] [[nodiscard]] bool isEmpty() const;
[[nodiscard]] int size() const;
int index(T) noexcept;
T priorElem(T) noexcept(false);
T nextElem(T) noexcept(false);
void add(T) noexcept;
void addAsPre(T) noexcept;
void mylistInsert(int index, T t) noexcept(false);
void mylistDelete(int index) noexcept(false);
};
template<typename T>
MyList<T>::MyList(const MyList<T>& li) : MyList() {
size_ = li.size_;
Node* p = li.LNode.next;
Node* tmp = LNode;
while (p) {
Node* node = new Node;
tmp->next = node;
node->data = p->data;
node->prior = tmp;
tmp = node;
p = p->next;
}
rear = tmp;
}
template<typename T>
MyList<T>& MyList<T>::operator=(const MyList& li) {
if (this == &li)
return *this;
clear();
size_ = li.size_;
Node* p = li.LNode.next;
Node* tmp = LNode;
while (p) {
Node* node = new Node;
tmp->next = node;
node->data = p->data;
node->prior = tmp;
tmp = node;
p = p->next;
}
rear = tmp;
return *this;
}
template<typename T>
MyList<T>::~MyList() {
clear();
}
template<typename T>
T MyList<T>::operator[](int index) const noexcept(false) {
if (index < 0 || index > size_ - 1)
throw out_of_range("The index is illegal!");
Node* p = LNode.next;
int i = 0;
while (i != index) {
p = p->next;
i++;
}
return p->data;
}
template<typename T>
T& MyList<T>::operator[](int index) noexcept(false) {
if (index < 0 || index > size_ - 1)
throw out_of_range("The index is illegal!");
Node* p = LNode.next;
int i = 0;
while (i != index) {
p = p->next;
i++;
}
return p->data;
}
template<typename T>
void MyList<T>::clear() {
Node* p = LNode.next;
while (p) {
Node* tmp = p->next;
delete p;
p = tmp;
}
LNode.next = nullptr;
size_ = 0;
rear = front;
}
template<typename T>
[[maybe_unused]] bool MyList<T>::isEmpty() const {
return front == rear;
}
template<typename T>
int MyList<T>::size() const {
return size_;
}
template<typename T>
int MyList<T>::index(T t) noexcept {
Node* p = LNode.next;
int i = 0;
while (p) {
if (p->data == t)
return i;
i++;
p = p->next;
}
return -1;
}
template<typename T>
T MyList<T>::priorElem(T t) noexcept(false) {
Node* p = LNode.next;
if (p && p->data == t)
throw logic_error("该元素在第一位,没有前驱!");
if (p)
p = p->next;
while (p) {
if (p->data == t)
return p->prior->data;
p = p->next;
}
throw logic_error("没有该元素!");
}
template<typename T>
T MyList<T>::nextElem(T t) noexcept(false) {
Node* p = LNode.next;
while (p) {
if (p->data == t) {
if (p->next)
return p->next->data;
throw invalid_argument("该元素在最后,没有后继!");
}
p = p->next;
}
throw invalid_argument("该元素没有后继!");
}
template<typename T>
void MyList<T>::add(T t) noexcept {
size_++;
Node* node = new Node;
node->data = t;
node->prior = rear;
rear->next = node;
rear = node;
}
template<typename T>
void MyList<T>::mylistInsert(int index, T t) noexcept(false) {
if (index < 0 || index > size_ - 1)
throw domain_error("位置不正确,插入失败!");
++size_;
Node* p = LNode.next;
int i = 0;
while (i != index) {
p = p->next;
i++;
}
Node* node = new Node;
node->data = t;
node->next = p;
node->prior = p->prior;
p->prior->next = node;
p->prior = node;
}
template<typename T>
void MyList<T>::mylistDelete(int index) noexcept(false) {
if (index < 0 || index > size_ - 1)
throw out_of_range("位置不正确,删除失败!");
--size_;
Node* p = LNode.next;
int i = 0;
while (i != index) {
p = p->next;
i++;
}
p->prior->next = p->next;
if (!p->next)
rear = p;
else
p->next->prior = p->prior;
delete p;
}
template<typename T>
void MyList<T>::addAsPre(T t) noexcept {
Node* node = new Node;
size_++;
node->data = t;
node->prior = front;
if (size_ == 1)
{
node->next = nullptr;
front->next = node;
rear = node;
return;
}
node->next = front->next;
front->next->prior = node;
front->next = node;
}
#endif //TEST_EXPRIMENT3_MYLIST_H
主程序文件
#include <iostream>
#include<memory>
#include "MyList.h"
using namespace std;
template<typename T>
class MyList;
shared_ptr<MyList<int>> p;
void show_menu();
int main() noexcept {
show_menu();
int opt;
while (true) {
cout << "请输入你的选择:";
cin >> opt;
switch (opt) {
case 1: {
if (!p)
p = make_shared<MyList<int>>();
else
p->clear();
cout << "链表已初始化或重置成功!\n";
break;
}
case 2: {
if (!p)
cout << "未初始化链表或链表已被销毁。\n";
else {
p.reset();
cout << "链表销毁成功!\n";
}
break;
}
case 3: {
if (!p)
cout << "未初始化链表或链表已被销毁。\n";
else {
p->clear();
cout << "链表清空成功!\n";
}
break;
}
case 4: {
if (!p)
cout << "请先初始化一个链表!\n";
else
cout << "链表长度为" << p->size() << endl;
break;
}
case 5: {
if (!p)
cout << "请先初始化一个链表!\n";
else {
while (true) {
try {
cout << "请输入位序:";
int i = 0;
cin >> i;
printf_s("位序%d上的元素是%d\n", i, p->operator[](i));
break;
}
catch (const exception& e) {
cout << e.what();
cout << "\n请重新输入位序!\n";
}
}
}
break;
}
case 6: {
if (!p)
cout << "请先初始化一个链表!\n";
else {
cout << "请输入元素:";
int n = 0;
cin >> n;
int index = p->index(n);
if (index == -1)
cout << "不存在元素" << n << endl;
else
printf_s("元素%d的位序是%d\n", n, index);
}
break;
}
case 7: {
if (!p)
cout << "请先初始化一个链表!\n";
else {
while (true) {
try {
cout << "请输入元素:";
int n = 0;
cin >> n;
printf_s("元素%d的前驱是%d\n", n, p->priorElem(n));
break;
}
catch (const exception& e) {
cout << e.what();
cout << "请重新输入\n";
}
}
}
break;
}
case 8: {
if (!p)
cout << "请先初始化一个链表!\n";
else {
while (true) {
try {
cout << "请输入元素:";
int n = 0;
cin >> n;
printf_s("元素%d的后继是%d\n", n, p->nextElem(n));
break;
}
catch (const exception& e) {
cout << e.what();
cout << "请重新输入\n";
}
}
}
break;
}
case 9: {
if (!p)
cout << "请先初始化一个链表!\n";
else {
try {
cout << "请输入位置:";
int index = 0;
cin >> index;
cout << "请输入元素:";
int n = 0;
cin >> n;
p->mylistInsert(index, n);
cout << "插入成功!\n";
}
catch (const exception& e) {
cout << e.what() << endl;
}
}
break;
}
case 10: {
if (!p)
cout << "请先初始化一个链表!\n";
else {
try {
cout << "请输入位置:";
int index = 0;
cin >> index;
p->mylistDelete(index);
cout << "删除成功!\n";
}
catch (const exception& e) {
cout << e.what();
}
}
break;
}
case 11: {
if (!p)
cout << "请先初始化一个链表!\n";
else {
cout << "该链表的元素有:";
for (int i = 0; i < p->size(); ++i)
cout << p->operator[](i) << " ";
cout << endl;
}
break;
}
case 12: {
if (!p) {
p = make_shared<MyList<>>();
cout << "链表初始化成功,";
}
else {
p->clear();
cout << "已经清空已初始化的链表,";
}
cout << "请选择插入方式:1. 头插法 2. 尾插法" << endl;
int selection = 0;
while (selection != 1 && selection != 2) {
cout << "请输入1或2:";
cin >> selection;
}
cout << "请输入元素(以空格分隔,任意字母结尾,示例:1 2 3 4 5 6 q[ENTER]):";
int n = 0;
if (selection == 2)
while (cin >> n) p->add(n);
else
while (cin >> n) p->addAsPre(n);
cin.clear();
cin.sync();
while (cin.peek() != '\n') cin.get();
cout << "元素添加成功!\n";
break;
}
case 13: {
if (!p)
cout << "请先初始化一个链表!";
else {
for (int i = 0; i < p->size() / 2; ++i) {
int tmp = p->operator[](i);
p->operator[](i) = p->operator[](p->size() - 1 - i);
p->operator[](p->size() - 1 - i) = tmp;
}
cout << "单链表的逆序存放已完成" << endl;
}
break;
}
case 14:
system("cls");
show_menu();
break;
default:
cout << "请输入1-12以内的数!\n";
}
cout << endl << endl;
}
}
void show_menu() {
std::cout << "可执行的操作有:" << endl;
cout << "************************************************************\n"
<< "************ 1.初始化或重置链表 ***********\n"
<< "************ 2.销毁链表 ***********\n"
<< "************ 3.清空链表 ***********\n"
<< "************ 4.链表长度 ***********\n"
<< "************ 5.指定位置的元素值 ***********\n"
<< "************ 6.链表已存在元素的位序 ***********\n"
<< "************ 7.求输入元素的直接前驱 ***********\n"
<< "************ 8.求输入元素的直接后继 ***********\n"
<< "************ 9.在第i个位置插入一个元素 ***********\n"
<< "************ 10.删除第i个元素 ***********\n"
<< "************ 11.输出所有的链表元素 ***********\n"
<< "************ 12.初始化并用头插法(或尾插法)输入元素 ***********\n"
<< "************ 13.实现单链表的逆序存放 ***********\n"
<< "************ 14.清屏 ***********\n"
<< "************************************************************\n";
}