C++ 单向链表手动实现(课后作业版)
单向链表,并实现增删查改等功能
首先定义节点类,类成员包含当前节点的值和下一个节点的地址
/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 definition
template <typename T>
class LinkList {
public:
Node<T>* headnode;
LinkList();
LinkList(const T* arr, int len); //array initial
LinkList(const LinkList<T>& link);
~LinkList();
LinkList<T>& push_back(T n);
LinkList<T>& push_front(T n);
LinkList<T>& insert(int pos, int n, T* arr);
LinkList<T>& pop_front();
LinkList<T>& pop_back();
LinkList<T>& remove(int pos, int num);
LinkList<T>& reverse();
T& operator[](int n);
T& at(int n);
LinkList<T>& replace(int pos, int n, T* arr);
int getLen() {return len;}
void clear() {this->~LinkList();}
void display();
private:
int len = 0;
Node<T>* getNode(int n);
};
各个函数解释:
LinkList(); 默认构造函数
LinkList(const T* arr, int len); 一般构造函数
LinkList(const LinkList<T>& link) 拷贝构造函数
~LinkList(); 析构函数
LinkList<T>& push_back(T n); 在尾部添加一个元素
LinkList<T>& push_front(T n); 在头部添加一个元素
LinkList<T>& insert(int pos, int n, T* arr); 在pos处插入n个元素
LinkList<T>& pop_front(); 删除第一个节点
LinkList<T>& pop_back(); 删除最后一个节点
LinkList<T>& remove(int pos, int num); 删除pos开始的num个元素
LinkList<T>& reverse(); 反转链表
T& operator[](int n); 重载[ ]运算符,返回第n个节点的值
T& at(int n); 与[ ]一样,只不过会检查索引是否越界
LinkList<T>& replace(int pos, int n, T* arr); 替换n个节点
int getLen() {return len;} 返回长度,因为len是private
void clear() {this->~LinkList();} 清除链表
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 definition
template <typename T>
class LinkList {
public:
Node<T>* headnode;
LinkList();
LinkList(const T* arr, int len); //array initial
LinkList(const LinkList<T>& link);
~LinkList();
LinkList<T>& push_back(T n);
LinkList<T>& push_front(T n);
LinkList<T>& insert(int pos, int n, T* arr);
LinkList<T>& pop_front();
LinkList<T>& pop_back();
LinkList<T>& remove(int pos, int num);
LinkList<T>& reverse();
T& operator[](int n);
T& at(int n);
LinkList<T>& replace(int pos, int n, T* arr);
int getLen() {return len;}
void clear() {this->~LinkList();}
void display();
private:
int len = 0;
Node<T>* getNode(int n);
};
//default constructor
template <typename T>
LinkList<T>::LinkList() {
headnode = nullptr;
len = 0;
}
//normal constructor
template <typename T>
LinkList<T>::LinkList(const T* arr, int len) {
Node<T>* temp = nullptr;
Node<T>* node = nullptr;
if ( len < 0 ) {
cout << "[error]: illegal length of LinkList" << endl;
exit(0);
}
for ( int i = len-1; i >= 0; i-- ) {
node = new Node<T>(i);
node->value = *(arr+i);
node->next = temp;
temp = node;
node = nullptr;
}
headnode = temp;
this->len = len;
}
//copy constructor
template <typename T>
LinkList<T>::LinkList(const LinkList<T>& link) {
this->len = link.getLen();
this->headnode = link.headnode;
link.headnode = nullptr;
}
//deconstructor
template <typename T>
LinkList<T>::~LinkList() {
this->len = 0;
Node<T>* temp = headnode;
while ( headnode ) {
temp = headnode;
headnode = headnode->next;
delete temp;
temp = nullptr;
}
}
//display all elements in Linklist<T>
template <typename T>
void LinkList<T>::display() {
if ( len == 0 ) {
cout << "[warning]: can not disply empty linkedlist" << endl;
return;
}
Node<T> *node = headnode;
for ( int i = 0; i < len; i++ ) {
cout << node->value << " ";
node = node->next;
}
cout << endl;
}
//add one node at the last position
template <typename T>
LinkList<T>& LinkList<T>::push_back(T n) {
Node<T> *node = this->getNode(len-1);
if ( node->next == nullptr ) {
Node<T> *temp = new Node<T>(n);
node->next = temp;
this->len++;
}
return *this;
}
//add one node at the first position
template <typename T>
LinkList<T>& LinkList<T>::push_front(T n) {
Node<T>* node_new = new Node<T>(n);
node_new->next = headnode;
headnode = node_new;
this->len++;
return *this;
}
//insert elements to LinkList
template <typename T>
LinkList<T>& LinkList<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);
}
if ( pos == 0 ) {
for ( int i = 0; i < n; i++ )
this->push_front(arr[n-1-i]);
return *this;
}
Node<T>* node_N = getNode(pos-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;
this->len += n;
return *this;
}
//delete the first element
template <typename T>
LinkList<T>& LinkList<T>::pop_front() {
if ( this->len == 0 ) {
cout << "[error]: LinkList don't has any element" << endl;
exit(0);
}
Node<T>* temp = headnode;
headnode = getNode(1);
delete temp;
this->len--;
return *this;
}
//delete the last element
template <typename T>
LinkList<T>& LinkList<T>::pop_back() {
if ( this->len == 0 ) {
cout << "[error]: LinkList don't has any element" << endl;
exit(0);
}
Node<T>* temp = getNode(len-2);
delete temp->next;
temp->next = nullptr;
this->len--;
return *this;
}
//get the last node pointer
template <typename T>
Node<T>* LinkList<T>::getNode(int n) {
if ( n > len-1 || n < 0) {
cout << "[error]: index out of range" <<endl;
}
Node<T> *node = headnode;
for( int i = 0; i < n; i++ ) {
node = node->next;
}
return node;
}
//remove n elements
template <typename T>
LinkList<T>& LinkList<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);
}
if ( pos == 0 ) {
for ( int i = 0; i < num; i++ )
this->pop_front();
return *this;
}
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;
delete node;
if ( temp == node_N_num ) {
break;
}
}
node_N->next = node_N_num;
this->len -= num;
return *this;
}
//reverse linklist
template <typename T>
LinkList<T>& LinkList<T>::reverse() {
Node<T>* front = nullptr;
Node<T>* mid = headnode;
Node<T>* back = headnode->next;
while ( back ) {
mid->next = front;
front = mid;
mid = back;
back = back->next;
}
mid->next = front;
front = nullptr;
headnode = mid;
return *this;
}
template <typename T>
T& LinkList<T>::operator[](int n) {
if ( n > len-1 || n < 0 ) {
cout << "[error]: index out of range" << endl;
exit(0);
}
return this->getNode(n)->value;
}
template <typename T>
LinkList<T>& LinkList<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-1);
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<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(2,3);
link.display();
cout << "[] operator:" << endl;
cout << link[2] << endl;
cout << "replace:" << endl;
int a[] = {6,5,2};
link.replace(2, sizeof(a)/sizeof(int), a);
link.display();
cout << "linklist reserve:" << endl;
link.reverse();
link.display();
cout << "clear:" << endl;
link.clear();
cout << "len=" << link.getLen() << endl;
link.display();
}

C++ 单向链表手动实现(课后作业版)的更多相关文章
- 【云栖社区001-数据结构】如何实现一个高效的单向链表逆序输出(Java版)
如题 动手之前,发现自己很擅长用C语言来写链表. 不过,既然自己做的是Java开发,那么还是用Java实现这个算法吧:毕竟,以后的若干年里都差不多要跟Java打交道了. 于是,先将Java版的链表自学 ...
- Python3玩转单链表——逆转单向链表pythonic版
[本文出自天外归云的博客园] 链表是由节点构成的,一个指针代表一个方向,如果一个构成链表的节点都只包含一个指针,那么这个链表就是单向链表. 单向链表中的节点不光有代表方向的指针变量,也有值变量.所以我 ...
- C#学习单向链表和接口 IList<T>
C#学习单向链表和接口 IList<T> 作者:乌龙哈里 时间:2015-11-04 平台:Window7 64bit,Visual Studio Community 2015 参考: M ...
- Alan Cox:单向链表中prev指针的妙用
之前发过一篇二级指针操作单向链表的例子,显示了C语言指针的灵活性,这次再探讨一个指针操作链表的例子,而且是一种完全不同的用法. 这个例子是linux-1.2.13网络协议栈里的,关于链表遍历& ...
- String字符串类课后作业
String动手动脑和课后作业 请运行以下示例代码StringPool.java,查看其输出结果.如何解释这样的输出结果?从中你能总结出什么? 结果: 总结:在Java中,内容相同的字串常量(&quo ...
- Reverse Linked List II 单向链表逆序(部分逆序)
0 问题描述 原题点击这里. 将单向链表第m个位置到第n个位置倒序连接.例如, 原链表:1->2->3->4->5, m=2, n =4 新链表:1->4->3-& ...
- JAVA第三周课后作业
JAVA课后作业 一.枚举类型 代码: enum Size{SMALL,MEDIUM,LARGE}; public cl ass EnumTest { public static void main( ...
- 【编程题目】输入一个单向链表,输出该链表中倒数第 k 个结点
第 13 题(链表):题目:输入一个单向链表,输出该链表中倒数第 k 个结点.链表的倒数第 0 个结点为链表的尾指针.链表结点定义如下: struct ListNode {int m_nKey;Lis ...
- java课后作业
课后作业之字串加密: 设计思想: 1.输入要加密的英文子串str 2.定义num=str的字符串长度 3.将字符串转化为单个字符 4.每个字符+3,向后移3个 5.定义str1,将新得到的每个字符加到 ...
- 输出单向链表中倒数第k个结点
描述 输入一个单向链表,输出该链表中倒数第k个结点,链表的倒数第0个结点为链表的尾指针. 链表结点定义如下: struct ListNode { int m_nKey; ListNode* ...
随机推荐
- (app笔记)Appium如何开启、配置、启用
1.安装adb 2.打开手机调试 3.连接手机 4.appium运行前,手机需要io.appium.uiautomator2.server 和 Appium Settings. 5.appium操作: ...
- Docker 安全加固
一.docker安全加固 1.利用LXCFS增强docker容器隔离性和资源可见性 (proc容器与宿主机之间是共享的 没有进行隔离) 此rpm包在真机桌面q目录中 需先传到虚拟机/root/下 在 ...
- js 防抖
// 防抖 作用:防止重复触发事件 var count = 1; var container = document.getElementById('container'); function getU ...
- Java笔记_构造方法/构造器
构造方法/构造器(constructor) 怎么来的?之前在创建对象时,是先把一个对象创建好后,再给这个对象的属性赋值,如果现在要求在创建一个对象时,就直接指定这个对象的属性,该怎么做?此时就可以 ...
- mybatis判断是否为空或null
<if test="catagoryCode != null and catagoryCode != ''"> AND train.CATAGORY_CODE = #{ ...
- Pytorch实战学习(九):进阶RNN
<PyTorch深度学习实践>完结合集_哔哩哔哩_bilibili Advance RNN 1.RNN分类问题 判断数据集中的每个名字所属的国家,共有18个国家类别 2.网络结构 ①基础R ...
- Android蓝牙固件升级 DFU-OTA 固件升级
1.添加 依赖包: implementation 'no.nordicsemi.android:dfu:1.11.0' 2.DfuService类继承 DfuBaseService package ...
- jmeter 添加断言和查看断言结果
在对应的请求下添加响应断言,这里我们添加响应文本来作为检查点,来检查上面的这个请求是否成功 断言和断言结果是成对出现的,是为了检查我们添加的断言是否验证成功,如下图,如果成功,里面就会有对应的结果,且 ...
- prometheus Alertmanager webhook
一.自定义邮件告警 二.使用docker部署微信机器人告警 1.制作镜像 2.启动容器和指定webhook容器 一.自定义邮件告警 在alertmanager服务的配置文件中指定自定义告警文件 # ...
- fatal error: openssl/ssl.h: No such file or director
$ sudo apt-get install libssl-dev