LinkList.h
#ifndef LINKLIST_H
#define LINKLIST_H
#include
#include
class LinkList {
friend std::ostream &operator<<(std::ostream &out, const LinkList &L);
friend LinkList* link2node2link(LinkList *obj);
public:
struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode* next) : val(x), next(next) {}
};
LinkList() {
_dummyHead = new ListNode(0);
_len = 0;
}
int get(int index) const; // 取得链表第index个数的值
void addAtHead(int val); // 头插法
void addAtTail(int val); // 尾插法
void addAtIndex(int index, int val); // 在第index个数之后插入
void deleteAtIndex(int index); // 删除第index个数
void reverseList(); // 反转链表
private:
ListNode *_dummyHead;
unsigned _len = 0;
};
int LinkList::get(int index) const {
if (index < 0 || index > (_len - 1)) return -1;
ListNode *cur = _dummyHead->next;
while (index--) {
cur = cur->next;
}
return cur->val;
}
void LinkList::addAtHead(int val) {
ListNode *newNode = new ListNode(val); // 用val创建新节点
newNode->next = _dummyHead->next;
_dummyHead->next = newNode;
++_len; // 注意增加链表长度
}
void LinkList::addAtTail(int val) {
ListNode *newNode = new ListNode(val);
ListNode *cur = _dummyHead;
while (cur->next) { // 遍历到表尾
cur = cur->next;
}
cur->next = newNode;
++_len; // 注意增加链表长度
}
void LinkList::addAtIndex(int index, int val) {
if (index < 0 || index > _len) return; // 判断是否超出范围
ListNode *newNode = new ListNode(val);
ListNode *cur = _dummyHead;
while (index--) {
cur = cur->next;
}
newNode->next = cur->next;
cur->next = newNode;
++_len;
}
void LinkList::deleteAtIndex(int index) {
if (index < 0 || index > (_len - 1)) return;
ListNode *cur = _dummyHead;
while (index--) {
cur = cur->next;
}
ListNode *tmp = cur->next;
cur->next = cur->next->next;
delete tmp;
--_len; // 注意删除后减小链表长度
}
void LinkList::reverseList() {
ListNode *cur = _dummyHead->next; // 从头节点出发
ListNode *node = nullptr; // 上一个节点
while (cur) {
LinkList::ListNode *tail = cur->next; // 保存下一个节点
cur->next = node; // 当前节点的下一位变成上一个节点
node = cur; // 上一个节点后移
cur = tail; // 跳到原链表中下一个需要处理的节点
}
_dummyHead->next = node;
}
std::ostream &operator<<(std::ostream &out, const LinkList &L) {
LinkList::ListNode *p = L._dummyHead->next;
while (p) {
out << p->val << "->";
p = p->next;
}
// 输出样式 1->2->3
out << "\b\b "; // 删除最后的->,最后一个\b后有两个空格
return out;
}
// 将容器中的数值使用尾插法添加到链表中
void vector2list(const std::vector<int> &vec, LinkList *obj) {
if (vec.empty()) {
return;
}
for (const auto &i : vec) {
obj->addAtTail(i);
}
return;
}
#endif // LINKLIST_H
LinkList.cpp
#include
#include
#include "LinkList.h"
using namespace std;
int main()
{
vector<int> list = {1, 2, 2, 3, 4, 5, 3, 3, 3, 4, 5};
LinkList *obj = new LinkList();
vector2list(list, obj);
cout << "构建链表:" << endl;
cout << *obj << endl;
cout << "链表第2个节点的值为:";
cout << obj->get(2) << endl;
cout << "头插法,在链表之前插入0:" << endl;
obj->addAtHead(0);
cout << *obj << endl;
cout << "尾插法,在链表末尾插入0:" << endl;
obj->addAtTail(0);
cout << *obj << endl;
cout << "在第一个节点后插入99:" << endl;
obj->addAtIndex(1, 99);
cout << *obj << endl;
cout << "删除第一个元素:" << endl;
obj->deleteAtIndex(0);
cout << *obj << endl;
cout << "反转链表:" << endl;
obj->reverseList();
cout << *obj << endl;
return 0;
}
struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode* next) : val(x), next(next) {}
};
链表有两个成员变量:一个伪头节点_dummyHead
和链表长度_len
。
Class LinkList {
Private:
ListNode *_dummyHead;
unsigned _len = 0;
}
构造头节点之前的伪头节点_dummyHead
方便进行头插法。
LinkList() {
_dummyHead = new ListNode(0);
_len = 0;
}
链表包含:取值,插入元素,删除元素和反转链表的功能。
int get(int index) const; // 取得链表第index个数的值
void addAtHead(int val); // 头插法
void addAtTail(int val); // 尾插法
void addAtIndex(int index, int val); // 在第index个数之后插入
void deleteAtIndex(int index); // 删除第index个数
void reverseList(); // 反转链表
// 输出链表值
friend std::ostream &operator<<(std::ostream &out, const LinkList &L);
int LinkList::get(int index) const {
if (index < 0 || index > (_len - 1)) return -1;
ListNode *cur = _dummyHead->next;
while (index--) {
cur = cur->next;
}
return cur->val;
}
首先判断index是否在链表范围内,若不在返回 -1 。
// 头插法
void LinkList::addAtHead(int val) {
ListNode *newNode = new ListNode(val); // 用val创建新节点
newNode->next = _dummyHead->next;
_dummyHead->next = newNode;
++_len; // 注意增加链表长度
}
一定注意要增加链表长度 _len
。
// 尾插法
void LinkList::addAtTail(int val) {
ListNode *newNode = new ListNode(val);
ListNode *cur = _dummyHead;
while (cur->next) { // 遍历到表尾
cur = cur->next;
}
cur->next = newNode;
++_len; // 注意增加链表长度
}
void LinkList::addAtIndex(int index, int val) {
if (index < 0 || index > _len) return; // 判断是否超出范围
ListNode *newNode = new ListNode(val);
ListNode *cur = _dummyHead;
while (index--) {
cur = cur->next;
}
newNode->next = cur->next;
cur->next = newNode;
++_len;
}
if (index < 0 || index > _len)
中上限宽松了一位,因为在_index - 1
处也可以插入元素。
void LinkList::deleteAtIndex(int index) {
if (index < 0 || index > (_len - 1)) return;
ListNode *cur = _dummyHead;
while (index--) {
cur = cur->next;
}
ListNode *tmp = cur->next;
cur->next = cur->next->next;
delete tmp;
--_len; // 注意删除后减小链表长度
}
void LinkList::reverseList() {
ListNode *cur = _dummyHead->next; // 从头节点出发
ListNode *node = nullptr; // 上一个节点
while (cur) {
LinkList::ListNode *tail = cur->next; // 保存下一个节点
cur->next = node; // 当前节点的下一位变成上一个节点
node = cur; // 上一个节点后移
cur = tail; // 跳到原链表中下一个需要处理的节点
}
_dummyHead->next = node;
}
std::ostream &operator<<(std::ostream &out, const LinkList &L) {
LinkList::ListNode *p = L._dummyHead->next;
while (p) {
out << p->val << "->";
p = p->next;
}
// 输出样式 1->2->3
out << "\b\b "; // 删除最后的->,最后一个\b后有两个空格
return out;
}
重载<<。注意 "\b\b " 后有两个空格。