单向循环链表,并实现增删查改等功能

首先定义节点类,类成员包含当前节点的值, 指向下一个节点的指针

循环链表的尾节点指向头节点

节点定义:

//node definition
template <typename T>
class Node {
public:
T value;
Node<T>* next; Node() {}
Node(const T& value) {
this->value = value;
next = nullptr;
}
Node(const T& value, const Node<T>& next) {
this->value = value;
this->next = next;
}
};

然后是链表类的定义,主要包含了增删查改等功能

//LinkList_cycle definition
template <typename T>
class LinkList_cycle {
public:
Node<T>* headnode; LinkList_cycle();
LinkList_cycle(const T* arr, int len); //array initial
LinkList_cycle(const LinkList_cycle<T>& link);
~LinkList_cycle();
LinkList_cycle<T>& push_back(T n);
LinkList_cycle<T>& push_front(T n);
LinkList_cycle<T>& insert(int pos, int n, T* arr);
LinkList_cycle<T>& pop_front();
LinkList_cycle<T>& pop_back();
LinkList_cycle<T>& remove(int pos, int num);
LinkList_cycle<T>& reverse();
T& operator[](int n);
T& at(int n);
LinkList_cycle<T>& replace(int pos, int n, T* arr);
int getLen() {return len;}
void clear() {this->~LinkList_cycle();}
void display();
private:
int len = 0;
Node<T>* getNode(int n); };

各个函数解释:

LinkList_cycle();      默认构造函数

LinkList_cycle(const T* arr, int len);      一般构造函数

LinkList_cycle(const LinkList_cycle<T>& link)           拷贝构造函数

~LinkList_cycle();     析构函数

LinkList_cycle<T>& push_back(T n);    在尾部添加一个元素

LinkList_cycle<T>& push_front(T n);     在头部添加一个元素

LinkList_cycle<T>& insert(int pos, int n, T* arr);   在pos处插入n个元素

LinkList_cycle<T>& pop_front();    删除第一个节点

LinkList_cycle<T>& pop_back();    删除最后一个节点

LinkList_cycle<T>& remove(int pos, int num);     删除pos开始的num个元素

LinkList_cycle<T>& reverse();     反转链表

T& operator[](int n);     重载[ ]运算符,返回第n个节点的值

T& at(int n);                 与[ ]一样,只不过会检查索引是否越界

LinkList_cycle<T>& replace(int pos, int n, T* arr);    替换n个节点

int getLen() {return len;}     返回长度,因为len是private

void clear() {this->~LinkList_cycle();}    清除链表

void display();    显示链表所有元素

Node<T>* getNode(int n);     返回第n个节点的指针,是private函数,在其他函数中经常用到

完整代码:

#include <iostream>
using namespace std; //node definition
template <typename T>
class Node {
public:
T value;
Node<T>* next; Node() {}
Node(const T& value) {
this->value = value;
next = nullptr;
}
Node(const T& value, const Node<T>& next) {
this->value = value;
this->next = next;
}
}; //LinkList_cycle definition
template <typename T>
class LinkList_cycle {
public:
Node<T>* headnode; LinkList_cycle();
LinkList_cycle(const T* arr, int len); //array initial
LinkList_cycle(const LinkList_cycle<T>& link);
~LinkList_cycle();
LinkList_cycle<T>& push_back(T n);
LinkList_cycle<T>& push_front(T n);
LinkList_cycle<T>& insert(int pos, int n, T* arr);
LinkList_cycle<T>& pop_front();
LinkList_cycle<T>& pop_back();
LinkList_cycle<T>& remove(int pos, int num);
LinkList_cycle<T>& reverse();
T& operator[](int n);
T& at(int n);
LinkList_cycle<T>& replace(int pos, int n, T* arr);
int getLen() {return len;}
void clear() {this->~LinkList_cycle();}
void display();
private:
int len = 0;
Node<T>* getNode(int n); }; //default constructor
template <typename T>
LinkList_cycle<T>::LinkList_cycle() {
headnode = nullptr;
len = 0;
} //normal constructor
template <typename T>
LinkList_cycle<T>::LinkList_cycle(const T* arr, int len) {
Node<T>* temp = nullptr;
Node<T>* node = nullptr;
if ( len < 0 ) {
cout << "[error]: illegal length of LinkList_cycle" << endl;
exit(0);
}
node = new Node<T>(arr[0]);
headnode = node;
temp = node;
for ( int i = 1; i < len; i++ ) {
node = nullptr;
node = new Node<T> (arr[i]);
temp->next = node;
temp = temp->next;
}
temp->next = headnode;;
this->len = len;
} //copy constructor
template <typename T>
LinkList_cycle<T>::LinkList_cycle(const LinkList_cycle<T>& link) {
this->len = link.getLen();
this->headnode = link.headnode;
} //deconstructor
template <typename T>
LinkList_cycle<T>::~LinkList_cycle() {
if ( headnode == nullptr || len == 0 ) {
headnode = nullptr;
len = 0;
return;
}
this->len = 0;
Node<T>* temp1 = headnode;
Node<T>* temp2 = headnode; //保存headnode
while ( headnode != nullptr ) {
temp1 = headnode;
headnode = headnode->next;
delete temp1;
if ( headnode == temp2 ) //如果next指向headnode了,说明当前的temp1就是最后一个节点了
break;
temp1 = nullptr;
}
headnode = nullptr;
} //display all elements in LinkList_cycle<T>
template <typename T>
void LinkList_cycle<T>::display() {
if ( this->len == 0 ) {
cout << "[warning]: can not display empty linkedlist" << endl;
return;
}
Node<T> *node = headnode;
for ( int i = 0; i < len; i++ ) {
cout << node->value << " ";
node = node->next;
}
if ( node != headnode ) {
cout << "[error]: the last node->next do not point to headnode, check again" << endl;
}
node = nullptr;
cout << endl;
} //add one node at the last position
template <typename T>
LinkList_cycle<T>& LinkList_cycle<T>::push_back(T n) {
Node<T> *node = this->getNode(len-1); //获取指向第len-1个node的指针,即len-2节点的next,所以node就是指向最后节点的指针 if ( node->next == headnode ) { //再加一层保护
Node<T> *temp = new Node<T>(n); //创建新node
node->next = temp; //将最后一个节点的next指向新node
temp->next = headnode; //将新node->next指向headnode
this->len++;
}
return *this;
} //add one node at the first position
template <typename T>
LinkList_cycle<T>& LinkList_cycle<T>::push_front(T n) {
Node<T>* node_new = new Node<T>(n); //新节点
Node<T> *node_end = this->getNode(len-1); //最后节点
node_new->next = headnode; //新节点的next指向第一个节点
node_end->next = node_new; //最后节点的next指向新节点
headnode = node_new; //再让headnode指向新节点
this->len++;
return *this;
} //insert elements to LinkList_cycle
template <typename T>
LinkList_cycle<T>& LinkList_cycle<T>::insert(int pos, int n, T* arr) {
if ( pos > len-1 || len < 0 ) {
cout << "[error]: illegal insert position, please check again" << endl;
exit(0);
}
Node<T>* node_N = getNode(len-1); //前半部分
Node<T>* temp = node_N->next; //后半部分
Node<T>* node_new = nullptr; //新增加的
for ( int i = 0; i < n; i++ ) {
node_new = new Node<T> (arr[n-1-i]);
node_new->next = temp;
temp = node_new;
node_new = nullptr;
}
node_N->next = temp;
if ( pos == 0) //唯有再0处插入的时候,需要改变头节点,其实对pos=0,一直push_front也行
headnode = temp;
this->len += n;
return *this;
} //delete the first element
template <typename T>
LinkList_cycle<T>& LinkList_cycle<T>::pop_front() {
if ( this->len == 0 ) {
cout << "[error]: LinkList_cycle don't has any element" << endl;
exit(0);
}
Node<T>* temp = headnode; //先复制一份headnode
headnode = headnode->next; //headnode 前进一步
delete temp; //把第一个节点释放掉
this->len--;
temp = getNode(len-1); //获取最后一个节点
temp->next = headnode; //把最后一个节点的next指向新的headnode
return *this;
} //delete the last element
template <typename T>
LinkList_cycle<T>& LinkList_cycle<T>::pop_back() {
if ( this->len == 0 ) {
cout << "[error]: LinkList_cycle don't has any element" << endl;
exit(0);
}
Node<T>* temp1 = getNode(len-2);
Node<T>* temp2 = temp1->next;
delete temp2;
temp1->next = headnode;
this->len--;
return *this;
} //get the last node pointer
template <typename T>
Node<T>* LinkList_cycle<T>::getNode(int n) {
if ( n > len-1 || n < 0) {
cout << "[warning]: index out of range" <<endl;
}
n = n%len;
if ( n < 0 )
n = n + len;
Node<T> *node = headnode;
for( int i = 0; i < n; i++ ) {
node = node->next;
}
return node;
} //remove n elements
template <typename T>
LinkList_cycle<T>& LinkList_cycle<T>::remove(int pos, int num) {
if ( pos > len-1 || len < 0 ) {
cout << "[error]: illegal remove position, please check again" << endl;
exit(0);
} else if ( pos + num > len) {
cout << "[error]: remove index out of range" << endl;
exit(0);
}
Node<T>* node_N = getNode(pos-1);
Node<T>* node_N_num = getNode(pos+num);
Node<T>* temp = getNode(pos);
while ( 1 ) {
Node<T>* node = temp;
temp = temp->next;
if ( temp == node_N_num ) {
break;
}
delete node;
}
if ( pos == 0 ) { //如果从0位置开始删除,要修改头节点
headnode = node_N_num;
node_N->next = headnode;
}
node_N->next = node_N_num;
this->len -= num;
return *this;
} //reverse LinkList_cycle
template <typename T>
LinkList_cycle<T>& LinkList_cycle<T>::reverse() {
const int num = len;
T arr[num];
Node<T>* temp = headnode;
for ( int i = 0; i < this->len; i++ ) {
arr[i] = temp->value;
temp = temp->next;
}
temp = headnode;
for ( int i = 0; i < this->len; i++ ) {
temp->value = arr[len-i-1];
temp = temp->next;
}
return *this;
} template <typename T>
T& LinkList_cycle<T>::operator[](int n) {
return this->getNode(n)->value;
} template <typename T>
LinkList_cycle<T>& LinkList_cycle<T>::replace(int pos, int n, T* arr) {
if ( pos > len-1 || len < 0 ) {
cout << "[error]: illegal remove position, please check again" << endl;
exit(0);
} else if ( pos + n > len) {
cout << "[error]: remove index out of range" << endl;
exit(0);
}
Node<T>* temp = nullptr;
if ( pos == 0 )
temp = headnode;
else
temp = this->getNode(pos);
for ( int i = 0; i < n; i++ ) {
temp->value = arr[i];
temp = temp->next;
}
return *this;
} int main(){
int arr[]{1,2,4,5,0};
LinkList_cycle<int> link(arr, sizeof(arr)/sizeof(int));
cout << "LinkLint init with arr: " <<endl;
link.display();
cout << "push_back:" << endl;
link.push_back(34);
link.display();
cout << "push_front:" << endl;
link.push_front(10);
link.display();
cout << "insert:" << endl;
link.insert(0,4,arr);
link.display();
cout << "pop_front:" << endl;
link.pop_front();
link.display();
cout << "pop_back:" << endl;
link.pop_back();
link.display();
cout << "remove:" << endl;
link.remove(0,3);
link.display();
cout << "[] operator:" << endl;
cout << link[2] << endl;
cout << "replace:" << endl;
int a[] = {6,5,2};
link.replace(0, sizeof(a)/sizeof(int), a);
link.display();
cout << "LinkList_cycle reserve:" << endl;
link.reverse();
link.display();
cout << "clear:" << endl;
link.clear();
cout << "len=" << link.getLen() << endl;
link.display();
}

C++ 手动实现单向循环链表(课后作业版)的更多相关文章

  1. String字符串类课后作业

    String动手动脑和课后作业 请运行以下示例代码StringPool.java,查看其输出结果.如何解释这样的输出结果?从中你能总结出什么? 结果: 总结:在Java中,内容相同的字串常量(&quo ...

  2. JAVA第三周课后作业

    JAVA课后作业 一.枚举类型 代码: enum Size{SMALL,MEDIUM,LARGE}; public cl ass EnumTest { public static void main( ...

  3. java课后作业

    课后作业之字串加密: 设计思想: 1.输入要加密的英文子串str 2.定义num=str的字符串长度 3.将字符串转化为单个字符 4.每个字符+3,向后移3个 5.定义str1,将新得到的每个字符加到 ...

  4. 基于visual Studio2013解决算法导论之021单向循环链表

     题目 单向循环链表的操作 解决代码及点评 #include <stdio.h> #include <stdlib.h> #include <time.h> ...

  5. Python 单向循环链表

    操作 is_empty() 判断链表是否为空 length() 返回链表的长度 travel() 遍历 add(item) 在头部添加一个节点 append(item) 在尾部添加一个节点 inser ...

  6. 单向循环链表C语言实现

    我们都知道,单向链表最后指向为NULL,也就是为空,那单向循环链表就是不指向为NULL了,指向头节点,所以下面这个程序运行结果就是,你将会看到遍历链表的时候就是一个死循环,因为它不指向为NULL,也是 ...

  7. python中的单向循环链表实现

    引子 所谓单向循环链表,不过是在单向链表的基础上,如响尾蛇般将其首尾相连,也因此有诸多类似之处与务必留心之点.尤其是可能涉及到头尾节点的操作,不可疏忽. 对于诸多操所必须的遍历,这时的条件是什么?又应 ...

  8. python基础一之课后作业:编写登录接口

    1 # Author : Mamba 2 3 #python基础一之课后作业:编写登录接口 4 5 # 输入用户名密码 6 # 认证成功后显示欢迎信息 7 # 用户名3次输入错误后,退出程序 8 # ...

  9. c/c++ 线性表之单向循环链表

    c/c++ 线性表之单向循环链表 线性表之单向循环链表 不是存放在连续的内存空间,链表中的每个节点的next都指向下一个节点,最后一个节点的下一个节点不是NULL,而是头节点.因为头尾相连,所以叫单向 ...

  10. 吴恩达课后作业学习1-week4-homework-two-hidden-layer -1

    参考:https://blog.csdn.net/u013733326/article/details/79767169 希望大家直接到上面的网址去查看代码,下面是本人的笔记 两层神经网络,和吴恩达课 ...

随机推荐

  1. Ubuntu18.04LTS虚拟机优化

    1.没网 刚安装好没网,可以设置NAT连接,也可以直接设置为桥接模式联网.这里直接桥接. 网络中心使用的是以太网,所以就在菜单的"编辑"里的"虚拟网络编辑器"里 ...

  2. CentOS 7 忘记root密码的解决方法

    这是自己忘记密码root密码第二次了,可以再一再二但是不能再三.因此在此记录在网上找的 如何更换root密码的方法. (这篇文章是参考https://blog.csdn.net/q290994/art ...

  3. gitee 操作

    腾讯软件搜索 腾讯软件中心-海量软件高速下载 (qq.com) git,下载 git,安装.右键git bash here,输入,Git clone url地址.输入码云用户名密码,下载 $ Git ...

  4. Pyqtgraph入门

    一.介绍 1.1 什么是pyqtgraph? PyQtGraph是Python的图形和用户界面库,它充分利用PyQt和PtSide的高质量的图形表现水平和NumPy的快速科学计算与处理能力,在数学.科 ...

  5. VUE使用axios数据请求时报错 TypeError: Cannot set property 'xxxx' of undefined 的解决办法

    正常定义全局变量: data:function (){ return{ currentOrders:[] } }, 使用Axios发送请求并获取后端数据时,如果在then中使用this.current ...

  6. 无界面Linux系统和Windows系统使用selenium爬取CNVD数据

    因为CNVD官网采用了反爬机制,所以使用selenium能够更容易的爬取漏洞数据 1.在Windows中使用 注意根据chrome版本下载对应chromedriver 2.在无界面的Linux中使用 ...

  7. C 标准 C89/C90/C99/C11/C17

    C89/C90 PDF:https://www.yodaiken.com/wp-content/uploads/2021/05/ansi-iso-9899-1990-1.pdf C99 PDF:htt ...

  8. usb 2.0枚举过程

    device枚举过程: hub枚举过程:

  9. system verilog与C语言的接口(包含使用方法以及实例)

    资料来源 (1) sv绿皮书; (2) vcs user guide; (3) https://www.cnblogs.com/studyforever/p/5169243.html (4) syst ...

  10. idea的小tip

    1. 校验正则表达式 String类型的matches方法中键入option+return选择 check regexp可以测试正则的正确性