一、链表基础
链表的类型有三种:单链表、双链表、循环链表
单链表:
双链表:
循环链表:
链表与数组的对比:
二、链表结构体的定义
//初始化列表形式
struct ListNode{
int value;
ListNode *next;
ListNode(int v,ListNode *node):value(v),next(node){}
ListNode(int v):value(v),next(nullptr){}
ListNode():value(0),next(nullptr){}
};
三、创建一个链表
//创建链表方式1
ListNode *head=nullptr;
for(int i=0;i<5;i++){
head=new ListNode(i,head);
}
ListNode *dummy=new ListNode(0,head);//哑指针
//创建链表方式2
ListNode *head1=new ListNode(1,new ListNode(2,new ListNode(3,nullptr)));
ListNode *dummy1=new ListNode(0,head);//哑指针
四、链表遍历
void print(){
ListNode* cur=dummy;
while(cur->next){
cout<<cur->next->value<<endl;
cur=cur->next;
}
cout<<endl;
}
五、链表其他基本操作(插入、删除、检索)
class MyLinkedList {
public:
struct ListNode{
int val;
ListNode* next;
ListNode(int v,ListNode* node):val(v),next(node){}
ListNode(int v):val(v),next(nullptr){}
ListNode():val(0),next(nullptr){}
};
ListNode* dummy; //哑节点
int size; //链表大小
MyLinkedList() {
dummy=new ListNode(0);
size=0;
}
//获取第index个位置链表的值
int get(int index) {
if(index>=size || index<0) return -1;
ListNode* head=dummy->next;
for(int i=0;i<index;i++){
head=head->next;
}
return head->val;
}
//在链表头插入一个节点
void addAtHead(int val) {
ListNode* head=new ListNode(val,dummy->next);
dummy->next=head;
size++;
}
//在链表尾插入一个节点
void addAtTail(int val) {
ListNode* tail=new ListNode(val);
ListNode* head=dummy;
while(head->next){
head=head->next;
}
head->next=tail;
size++;
}
//在链表第index个位置前插入一个节点
void addAtIndex(int index, int val) {
if(index>size) return;
if(index<0) addAtHead(val);
else if(index==size) addAtTail(val);
else {
ListNode* head=dummy;
for(int i=0;i<index;i++){
head=head->next;
}
ListNode* newnode=new ListNode(val,head->next);
head->next=newnode;
size++;
}
}
//删除链表第index个位置的节点
void deleteAtIndex(int index) {
if(index<0 || index>=size) return;
ListNode* head=dummy;
for(int i=0;i<index;i++){
head=head->next;
}
ListNode* del=head->next;
head->next=head->next->next;
delete del;
size--;
}
};
六、力扣典型链表题
//双指针法
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode*pre=nullptr;
ListNode*cur=head;
while(cur){
struct ListNode* next=cur->next;
cur->next=pre;
pre=cur;
cur=next;
}
return pre;
}
};
//递归法
class Solution {
public:
ListNode* reverse(ListNode* pre,ListNode* cur){
if(!cur) return pre;
ListNode* next=cur->next;
cur->next=pre;
return reverse(cur,next);
}
ListNode* reverseList(ListNode* head) {
return reverse(nullptr,head);
}
};
//哈希表
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
unordered_set<ListNode*> hashmap;
while(head){
if(hashmap.count(head)) //如果哈希表中有这个节点,说明为环的入口节点
return head;
hashmap.emplace(head);
head=head->next;
}
return NULL;
}
};
//双指针法
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode* slow=head;
ListNode* fast=head;
while(fast && fast->next){
slow=slow->next;
fast=fast->next->next;
if(slow==fast){ //快慢指针相遇
ListNode* circlenode=fast;
ListNode* cur=head; //从head开始往前走,与circlenode相遇位置就是环的入口
while(cur!=circlenode){
cur=cur->next;
circlenode=circlenode->next;
}
return cur;
}
}
return NULL;
}
};
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode *dummy=new ListNode(0,head);
ListNode *fast=head; //注意这快慢指针的设定
ListNode *slow=dummy;
for(int i=0;i<n;i++){
fast=fast->next;
}
while(fast){
fast=fast->next;
slow=slow->next;
}
ListNode *del=slow->next;
slow->next=slow->next->next;
delete del;//要在改变链表结构之后删除
return dummy->next;
}
};
class Solution {
public:
ListNode* mergetwo(ListNode* l1,ListNode* l2){
ListNode* merged=new ListNode(0);
ListNode* head=merged;
while(l1&&l2){
if(l1->val<l2->val){
merged->next=l1;
l1=l1->next;
}
else {
merged->next=l2;
l2=l2->next;
}
merged=merged->next;
}
merged->next=(l1?l1:l2);
return head->next;
}
ListNode* mergeKLists(vector<ListNode*>& lists) {
ListNode* result=new ListNode(INT_MIN); //注意INT_MIN,因为有负数
for(int i=0;i<lists.size();i++){
result=mergetwo(result,lists[i]);
}
return result->next;
}
};
class Solution {
public:
//链表排序一般使用归并排序
ListNode* sortList(ListNode* head) {
return sortList(head,nullptr);
}
ListNode* sortList(ListNode* head,ListNode* tail){
if(head==nullptr){ //注意!!
return head;
}
if(head->next==tail){ //注意!!
head->next=nullptr;
return head;
}
ListNode* slow=head;
ListNode* fast=head;//注意这快慢指针的写法!!
while(fast!=tail){
slow=slow->next;
fast=fast->next;
if(fast!=tail) fast=fast->next;
}
ListNode* mid=slow;
return merged(sortList(head,mid),sortList(mid,tail));
}
ListNode* merged(ListNode* l1,ListNode* l2){
ListNode* merged=new ListNode(0);
ListNode* dummy=merged;
while(l1&&l2){
if(l1->val<l2->val){
merged->next=l1;
l1=l1->next;
}
else{
merged->next=l2;
l2=l2->next;
}
merged=merged->next;
}
merged->next=(l1?l1:l2);
return dummy->next;
}
};