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* ...
随机推荐
- android studio有关grdle配置
我们每次新建工程的时候,项目都会通过该路径下寻找适合的gradle包,如果没有则会自动下载到对应的文件夹下
- Oracle常用的日期操作函数 to_char()和to_date
https://www.cnblogs.com/zhangliang88/p/12924407.html
- 01爬取豆瓣网电影数据进行numpy的练习
level 2:10.案例:编写爬虫爬取豆瓣电影排行榜(电影名称,评分),保存为csv文件 a.用numpy加载csv数据 b.把评分列转换成float64类型 c.计算电影的平均评分 d.求评分最高 ...
- spider_爬取斗图啦所有表情包(图片保存)
"""爬取斗图吧里面的所有表情包知识点总结: 一.使用requests库进行爬取,随机请求头(网站反爬措施少.挂个请求头足矣) 二.具体思路: 1.先爬取所有的图片url ...
- IIS7无法访问.apk文件的解决方法
随着智能手机的普及,越来越多的人使用手机上网,很多网站也应手机上网的需要推出了网站客户端,.apk文件就是安卓(Android)的应用程序后缀名,默认情况下,使用IIS作为Web服务器的无法访问下载此 ...
- moduleNotFoundError:No module named 'exceptions'
如果pip install docx 过请先卸载,输入如下指令: pip uninstall docx 方法一: pip install python-docx 方法二: 下载: python_doc ...
- 2023 新年FLAG 当你无所事事的时候,打开本博客看看,置顶着呢,别说你看不到,摸鱼狗
2023.2.15 接触到了Visual Grounding,但是是3D的,不知道这是不是冥冥之中的一颗种子,我现在有强烈的直觉我未来就是搞这个方向. 2023.2.14 回到学校正式开始工作 OK, ...
- @dynamicMemberLookup(动态成员查找)
动态成员查找是 Swift 中的一项功能特性,可提高与 Python 或 Javascript 等动态语言的互操作性.它允许动态成员查找调用看起来像访问类型属性的常规调用: let people = ...
- 关于DVWA踩坑
部署好DVWA开始欢天喜地用起来,结果有个问题,不管怎么设置这个安全等级,都显示为Impossible 原因也很显然 其实我并不太理解为什么这里要放在cookie里面,而且还放了两条. 处理方式也很明 ...
- 网线接口调试,Android ADB网络调试!
ADB网络调试,网线接口调试 没有USB接口,照样可以调试,可通过网线接口调试步骤! 一.第一步连接WIFI 查看wifi 的IP win+R 键 打开运行 ,输入cmd 二.输入ipc ...