第一次写博客,废话少讲,上代码:
一、创建一个链表的节点 node.h。
#pragma once //防止重复引入头文件
class Node{
public:
int data; //节点数据
Node *next; //下一个节点指针
public:
Node():data(-1),next(nullptr){} // 构造函数
}; //<-记得这里有分号
说明:
(1)由于我这里设计的节点数据是公开的,所以只有头文件就可以了,如需要对数据进行私有化可以自行添加其他方法。
(2)构造函数这样声明是在创建对象的时候设置默认属性值,data为-1,next是nullptr指针。
二、创建一个链表接口 List.h。
#pragma once //防止重复引入头文件
#include "Node.h" //引入节点头文件
class List{
private:
Node *head; //头节点指针
Node *tail; //尾节点指针
int size; //链表大小
public:
List(); //构造函数,初始化表头和表尾指针
void push(int data); //在尾部添加数据
bool insert(int pos,int data); //在指定的pos插入数据
bool remove(int pos); //删除指定pos位置的数据
void reverse(); //翻转链表
void print(); //打印链表数据
int operator[](int i); //重载运算符,让其通过 p[0]这样的方式访问链表数据
~List(); //析构函数,在释放此对象的时候删除节点
private:
Node* createNode(int data); //创建一个节点的工厂方法
}; //<-记得这里有分号
三、之后实现链表的内容 List.cpp
#include <iostream> //因为有print函数需求打印,所以引入输入输出流
#include "List.h" //引入list头文件
using namespace std; //加入命名空间
/*
* 构造函数
* 初始化head和tail指针,初始化size变量
*/
List::List(){
this->head = this->createNode(0); //新建立一个空白节点内容为头节点
this->tail = this->head; //当链表为空时,头指针和尾指针共同指向这个空白的节点
this->size = 0; //链表长度为0
}
/*
* 创建一个节点的工厂方法
*/
Node* List::createNode(int data){
Node *result = new Node();
result ->data = data;
return result;
}
/*
* 添加节点
*/
void List::push(int data){
this->tail->next = this->createNode(data); //在最尾节点添加新的节点
this->tail = this->tail->next; //更新最尾节点
this->size++; //长度加1
}
/*
* 在指定位置插入节点
*/
bool List::insert(int pos,int data){
if(pos < 0 || pos > this->size){
return false;
//如果插入的位置不存在返回false
}
else if(pos == this->size){
this->push(data);
return true;
//如果插入的位置刚好在最后面,则直接调用添加节点的函数返回true
}
//进行插入操作
Node *curr = this->head->next;
//取得第一个有数据的节点,不是头节点,头节点是空白的。
for(int i=0;i<pos-1;i++){
curr=curr->next;
}
//找到要插入的节点
Node *newNode = this->createNode(data);
//创建一个新的节点
newNode->next = curr->next;
//新节点的下一个节点指向插入点的下一个节点
curr->next = newNode;
//插入点的下一个节点指向新节点的下一个节
this->size++;
return true;
}
/*
* 删除节点
*/
bool List::remove(int pos){
if(pos < 0 || pos > this->size){
return false;
}
//如果删除的位置不存在返回false
Node* curr = this->head;
for(int i=1;i<pos;i++){
curr=curr->next;
}
Node* removeNode = curr->next;
//找到要删除的节点
curr->next = curr->next->next;
//把当前节点的下一个节点指向删除节点的下一个节点
delete removeNode;
//释放节点内存
this->size--;
//长度减1
return true;
}
/*
* 翻转链表
*/
void List::reverse(){
Node* prev = nullptr;
Node* curr = this->head->next;
//curr是第一个节点
while(curr != nullptr){
if(curr->next == nullptr){
this->head->next = curr;
//当前最后一个节点作为第一个节点存放
}
Node* next = curr->next;
//保存下一个节点的地址
curr->next = prev;
prev = curr;
curr = next;
}
}
/*
* 输出链表
*/
void List::print(){
if(this->size == 0){
cout << "size = 0 " << endl;
return ;
}
//如果链表为空的,输出 "size = 0 "
Node* curr = this->head->next;
while(curr!=nullptr){
cout<<curr->data<<" ";
curr = curr->next;
}
cout<<endl;
}
/*
*运算符重载,让其可以使用下标的方式取得数据
*/
int List::operator[](int i){
if(i<=0 || i>this->size){
return 0;
}
//如果下标超出当前数据范围,返回0
Node* curr = this->head->next;
for(int j=1;j<this->size;j++){
if(j==i){
return curr->data;
}
curr = curr->next;
}
}
/*
*析构函数 释放内存
*/
List::~List(){
Node* curr = this->head;
Node* delNode;
while(curr!=nullptr){
delNode = curr;
curr = curr->next;
delete delNode;
}
this->head = nullptr;
this->tail = nullptr;
this->size = 0;
cout << "delete!" << endl;
}
四、调用测试
#include <iostream>
// 引入输入输出流用作调用时候的输出
using namespace std;
// 加入std命名空间这样就可以使用cout cin这些方法了
int main()
{
List l;
l.push(2);
l.print();
l.push(3);
l.print();
l.push(6);
l.print();
l.insert(1,4);
l.print();
l.reverse();
l.print();
l.remove(3);
l.print();
return 0;
}
最后输出: