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

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

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

节点定义:

//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. docker下载java镜像,执行xxx.jar文件

    docker pull java:8u111

  2. 注意注意!!!!关于keil的问题,调试时候的bug

    1.keil变量不区分大小写: 2.KEIL调试debug时误报,未定义某变量 但是实际定义了的. 今天用keil写代码 感觉逻辑上没问题 但是始终不是那个效果 检查了半天错误问题.最后debug居然 ...

  3. Fiddler抓包原理与操作

    https://www.cnblogs.com/TankXiao/archive/2012/02/06/2337728.html#2306864

  4. 网络协议及osi模型

    osi模型:由高到底 应用层:最高一层,是用户与网络的接口 表示层: 会话层: 传输层:作用是为上层协议提供端到端的可靠和透明的数据传输服务 网络层: 数据链路层: 物理层:它利用传输介质为数据链路层 ...

  5. 对词向量模型Word2Vec和GloVe的理解

    Word2Vec Word2Vec 是 google 在2013年提出的词向量模型,通过 Word2Vec 可以用数值向量表示单词,且在向量空间中可以很好地衡量两个单词的相似性. 简述 我们知道,在使 ...

  6. class_task

    #!/usr/bin/python # -*- coding: UTF-8 -*- class Task():     _cls_name = "cls name"     def ...

  7. QueryDet: Cascaded Sparse Query for Accelerating High-Resolution Small Object Detection(QueryDet:用于加速高分辨率小目标检测的级联稀疏查询)

    QueryDet: Cascaded Sparse Query for Accelerating High-Resolution Small Object Detection(QueryDet:用于加 ...

  8. 力扣53. 最大子数组和(dp)

    给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. 子数组 是数组中的一个连续部分. 示例 1: 输入:nums = [-2,1,-3,4,-1 ...

  9. JS基础笔记汇总

    JS基础笔记最全的汇总 javascript介绍以及起源目录1.变量和常量的知识2.基本数据类型3.运算符4.基本数据类型间的转换5.流程控制语句 一.javascript介绍以及起源 js一种直译型 ...

  10. centons7.2 双网口聚合功能配置和验证

    1.启动网络管理器运行systemctl restart NetworkManager2.创建主备绑定连接 nmcli connection add con-name bond0 type bond ...