链表是由若干个结点组成的,内存可以不连续。一般定义数据域和指针域,一般链表的结点我们可以用结构体定义
由于链表的内存不连续,所以不支持随机访问(redis的跳表可以支持),但是插入和删除复杂度为O(1)
//单链表结点
struct ListNode{
int val;
struct ListNode * next;
ListNode(int v):val(v),next(nullptr){}
ListNode():next(nullptr){}
};
//树的结点
struct TreeNode{
int val;
struct TreeNode * left;
struct TreeNode * right;
//struct TreeNode * father;
TreeNode(int v):val(v),left(nullptr),right(nullptr){}
};
//双向链表的结点
struct TwoWayListNode{
int val;
struct TwoWayListNode * pre,*next;
TwoWayListNode(int v):val(v),pre(nullptr),next(nullptr){}
};
我们可以参考STL的list,底层是双向(循环)链表实现的,看看list中是如何定义的。我们先看一个试验:
#include
using namespace std;
int main(void) {
list<int> List;
List.push_back(100);
List.push_back(200);
List.push_back(300);
auto it = List.begin();
for(;it!=List.end();++it)
cout<<*it<<" "; cout<<endl;
cout<<*it<<endl;//输出end()
++it;
cout<<*it<<endl; //输出end()的下一个
it = List.begin();
cout<<*(--it)<<endl;
cout<<*(--it)<<endl;
return 0;
}
100 200 300
1
100
1
300
我们发现list的结构是一个循环链表,链表最后一个数据结点后是一个尾结点,end()指向这个尾结点,然后尾结点的next是链表的第一个数据元素。如下图
我们可以看一下list给我们调用的常用的函数接口有哪些:
一下是我写LRU算法中手写的双向链表List,实现了push_front(), pop_back(),erase(),设置了头结点head和尾结点tail,这样更方便写。
struct ListNode{
int key,val;//数据部分
struct ListNode * next;
struct ListNode * pre;
ListNode(int key=0,int val=0):key(key),val(val),next(nullptr),pre(nullptr){}
};
struct List{
int size;
ListNode * head;
ListNode * tail;
List() {
size = 0;
head = new ListNode();
tail = new ListNode();
head->next = tail;
tail->pre = head;
}
~List() {
ListNode * p = head,*t;
while(p) {
t = p->next;
delete p;
p = t;
}
}
ListNode * push_front(int key,int val) {
++size;
ListNode * t = new ListNode(key,val);
ListNode * p = head->next;
head->next = t;
t->next = p;
t->pre = head;
p->pre = t;
return t;
}
void push_front(ListNode * p) {
++size;
ListNode * t = head->next;
head->next = p;
p->next = t;
t->pre = p;
p->pre = head;
}
int pop_back() {
--size;
ListNode * p = tail->pre;
ListNode * t = p->pre;
t->next = tail;
tail->pre = t;
int k = p->key;
delete p;
return k;
}
void erase(ListNode * p) {
--size;
ListNode * pp = p->pre;
ListNode * pn = p->next;
pp->next = pn;
pn->pre = pp;
}
void toHead(ListNode *p) { //把某个结点移动到链表首部
erase(p);
push_front(p);
}
};
ListNode * Insertin_Sort(ListNode * head) {
if(!head||(head&&!head->next)) return head; //一个结点不需要排序
ListNode * hair = new ListNode(0);
hair->next = head;
ListNode * p = head;
while(p->next) {
ListNode * q = p->next;
if(q->val>=p->val) {
p = p->next;
continue;//这个是有序的,不用排
}
p->next = q->next;
ListNode * t = hair;
while(t->next->val <= q->val) t = t->next;
q->next = t->next;
t->next = q;
}
head = hair->next;
delete hair;
return head;
}
ListNode * MergeSort(ListNode * head) {
if(!head||(head&&!head->next)) return head;
ListNode * fast = head;
ListNode * slow = head;
while(fast->next&&fast->next->next) { //用快慢指针找到中点
fast = fast->next->next;
slow = slow->next;
}
ListNode * pR = MergeSort(slow->next);
slow->next = nullptr;
ListNode * pL = MergeSort(head);
ListNode * hair = new ListNode(0);
ListNode * p = hair;
while(pL||pR) {
if(!pR||(pL&&pL->val<=pR->val)) {
p->next = pL; pL = pL->next; p = p->next;
} else {
p->next = pR; pR = pR->next; p = p->next;
}
}
head = hair->next;
delete hair;
return head;
}
ListNode * ReverseList(ListNode * Head) {
if(!Head||(Head&&!Head->next)) return Head;
ListNode * p = ReverseList(Head->next);
Head->next->next = Head;
Head->next = nullptr;
return p;
}
ListNode * ReverseList2(ListNode * Head) {
if(!Head||(Head&&!Head->next)) return Head;
ListNode * tail = Head;
while(tail->next) tail = tail->next;
ListNode * last = tail->next; //nullptr
ListNode * p = Head;
while(last!=tail) {
ListNode * nex = p->next;
p->next = last;
last = p;
p = nex;
}
return tail;
}
ListNode * removeKth(ListNode * head,int k) { //删除第K个结点
if(k<=0) return head;
ListNode * hair = new ListNode(0);
hair->next = head;
ListNode * p = hair;
for(int i=1;i<k;++i) {
p = p->next;
if(!p->next) {
delete hair;
return head;
}
}
ListNode * q = p->next;
p->next = q->next;
delete q;
head = hair->next;
delete hair;
return head;
}
ListNode * removeRKth(ListNode * head,int k) {
if(k<=0) return head;
ListNode * hair = new ListNode(0);
hair->next = head;
ListNode *p = hair, *q = hair;
for(int i=1;i<=k;++i) {
p = p->next;
if(!p) {
delete hair;
return head;
}
}
while(p->next) {
p = p->next;
q = q->next;
}
p = q->next;
q->next = p->next;
delete p;
head = hair->next;
delete hair;
return head;
}
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
// 翻转一个子链表,并且返回新的头与尾
pair<ListNode*,ListNode*> RevLinkList(ListNode * head,ListNode * tail) {
ListNode * last = tail->next;
ListNode * p = head;
while(last!=tail) {
ListNode * nex = p->next;
p->next = last;
last = p;
p = nex;
}
return {tail,head};
}
ListNode* reverseKGroup(ListNode* head, int k) {
ListNode * hair = new ListNode(0);
hair->next = head;
ListNode * pre = hair;
while(head) {
ListNode * tail = pre;
for(int i=0;i<k;++i) {
tail = tail->next;
if(!tail) return hair->next; //后面的链表长度不足K
}
ListNode * nex = tail->next;
pair<ListNode*,ListNode*> res = RevLinkList(head,tail);
head = res.first;
tail = res.second;
tail->next = nex;
pre->next = head;
pre = tail;
head = tail->next;
}
return hair->next;
}
};
#include
using namespace std;
单链表结点
struct ListNode{
int val;
struct ListNode * next;
ListNode(int v):val(v),next(nullptr){}
ListNode():next(nullptr){}
};
struct LinkList{
ListNode * head;
int size;
LinkList();
void push_back(int);
void push_front(int);
void insertKth(int k,int v); //将结点v插入到链表第K个结点之前
bool removeKth(int k); //删除第K个结点
void show(); //按照[1,2,5]格式从到尾输出链表元素
bool removeRKth(int k); //删除倒数第K个结点
void destroy(); //删除链表,释放内存
~LinkList(); //析构函数
static ListNode * MergeSort(ListNode * head);//将单链表归并排序
void Merge_Sort(); //归并排序
static ListNode * ReverseList(ListNode * Head); //递归反转单链表
static ListNode * ReverseList2(ListNode * Head); //非递归反转单链表
void Reverse(); //反转链表
void Insertin_Sort(); //插入排序
};
LinkList::LinkList() { //无参构造函数
size = 0;
head = nullptr;
}
void LinkList::push_back(int v) {
++size;
ListNode * t = new ListNode(v);
if(!head) {
head = t;
return;
}
ListNode * p = head;
while(p->next) {
p = p->next;
}
p->next = t;
}
void LinkList::push_front(int v) {
++size;
ListNode * t = new ListNode(v);
if(!head) {
head = t;
return;
}
else {
t->next = head->next;
head->next = t;
}
}
void LinkList::insertKth(int k,int v) { //将结点v插入到链表第K个结点之前
++size;
ListNode * t = new ListNode(v);
assert(k>0&&k<=size);
if(k==1) {
t->next = head->next;
head = t;
} else {
ListNode * p = head;
for(int i=1;i<k;++i) p = p->next;
t->next = p->next;
p->next = t;
}
}
bool LinkList::removeKth(int k) { //删除第K个结点
if(k<=0||k>size) return false;
if(k==1) {
ListNode * p = head->next;
delete head;
head = p;
} else {
ListNode * p = head;
for(int i=2;i<k;++i) p = p->next;
ListNode * q = p->next;
p->next = q->next;
delete q;
}
return true;
}
void LinkList::show() {
if(!head) puts("[]");
else {
printf("[%d",head->val);
ListNode * p = head->next;
while(p) {
printf(" -> %d",p->val);
p = p->next;
}
printf("]\n");
}
}
bool LinkList::removeRKth(int k) { //删除倒数第K个结点
if(k<=0||k>size) return false;
assert(k>0&&k<=size);
ListNode * hair = new ListNode(0);
hair->next = head;
ListNode * p = hair,*q=hair;
for(int i=1;i<=k;++i) {
assert(p);
p = p->next;
}
while(p->next) {
p = p->next;
q = q->next;
}
p = q->next;
q->next = p->next;
delete p;
head = hair->next;
delete hair;
return true;
}
void LinkList::destroy() { //删除链表,释放内存
while(head) {
ListNode * nex = head->next;
delete head;
head = nex;
}
}
LinkList:: ~LinkList() {
destroy();
}
ListNode * LinkList::MergeSort(ListNode * head) {
if(!head||(head&&!head->next)) return head;
ListNode * fast = head;
ListNode * slow = head;
while(fast->next&&fast->next->next) {
fast = fast->next->next;
slow = slow->next;
}
ListNode * pR = MergeSort(slow->next);
slow->next = nullptr;
ListNode * pL = MergeSort(head);
ListNode * hair = new ListNode(0);
ListNode * p = hair;
while(pL||pR) {
if(!pR||(pL&&pL->val<=pR->val)) {
p->next = pL; pL = pL->next; p = p->next;
} else {
p->next = pR; pR = pR->next; p = p->next;
}
}
p = hair->next;
delete hair;
return p;
}
void LinkList::Merge_Sort() {
head = LinkList::MergeSort(head);
}
ListNode * LinkList::ReverseList(ListNode * Head) {
if(!Head||(Head&&!Head->next)) return Head;
ListNode * p = ReverseList(Head->next);
Head->next->next = Head;
Head->next = nullptr;
return p;
}
ListNode * LinkList::ReverseList2(ListNode * Head) {
if(!Head||(Head&&!Head->next)) return Head;
ListNode * tail = Head;
while(tail->next) tail = tail->next;
ListNode * last = tail->next; //nullptr
ListNode * p = Head;
while(last!=tail) {
ListNode * nex = p->next;
p->next = last;
last = p;
p = nex;
}
return tail;
}
void LinkList::Reverse() {
head = LinkList::ReverseList2(head);
}
void LinkList::Insertin_Sort() {
if(!head||(head&&!head->next)) return; //一个结点不需要排序
ListNode * hair = new ListNode(0);
hair->next = head;
ListNode * p = head;
while(p->next) {
ListNode * q = p->next;
if(q->val>=p->val) {
p = p->next;
continue;//这个是有序的,不用排
}
p->next = q->next;
ListNode * t = hair;
while(t->next->val <= q->val) t = t->next;
q->next = t->next;
t->next = q;
}
head = hair->next;
delete hair;
}
int main(void) {
LinkList List;
List.push_back(10);
List.push_back(20);
List.push_back(1);
List.push_back(5);
List.push_back(7);
List.push_back(100);
List.push_back(0);
List.push_back(1);
List.show();
List.Reverse();
List.show();
// List.Insertin_Sort();
List.Merge_Sort();
List.show();
return 0;
List.removeKth(1);
List.show();
List.removeKth(3);
List.show();
List.removeRKth(1);
List.show();
List.removeRKth(5);
List.show();
List.removeRKth(4);
List.show();
List.Reverse();
List.show();
return 0;
}
2020.9.7
0:17