一.单双链表的定义
struct LinkNode
{
int data;
struct LinkNode* node;
};
二.双链表的定义
struct DLNode
{
int val;
struct DLNode* next;
struct DLNode* last;
};
三.反转单链表
逆序之后要把头抓住
代码
注意head引用的传递,java和c++这点是一样的,f(head)内对head的操作是对head的拷贝副本进行的操作,不会改变head。
head直接代表的就是头结点,而不是一个指向头结点的空结点。那样想会把自己弄混。
ListNode* reverseList(ListNode* head)
{
ListNode* next=nullptr;
ListNode* pre=nullptr;
while(head!=nullptr)
{
next=head->next;//记一下head的next的走向,因为要反转
head->next=pre;
pre=head;
head=next;
}
return pre;
}
核心是要记住head的下一个位置,用next记住,要不然位置信息会丢失
反转链表的初始状态
记一下head的next指针的原始走向,因为要反转
这里相当于head置空
pre来到head的位置
head往下走
四.反转双链表
本质逻辑和反转单链表一样,只不过多了一根last指针要链接
DLNode* reverseDoubleList(DLNode* head)
{
DLNode* pre = nullptr;
DLNode* next = nullptr;
while (head != nullptr)
{
next = head->next;//记录下一个位置的信息
head->next = pre;//链接
head->last = next;//链接
pre = head;//为了链接,所以要移位
head = next;//把head移动到下一个位置,为了循环
}
return pre;
}
五.单链表实现队列
直接转载另一个哥们写的,链表主要考察的是coding能力
六.用单链表实现栈;
栈的实现与队的实现相似,而且更简单一些,因为只需要一个栈顶指针
#include<iostream>
using namespace std;
struct ListNode
{
int val;
struct ListNode* next;
};
template<typename V>
class MyStack
{
private:
ListNode* head;
int size;
public:
MyStack()
{
head = nullptr;
size = 0;
}
bool isEmpty()
{
return size == 0;
}
int size()
{
return size;
}
void push(V value)
{
ListNode* cur = new ListNode(value);
if (head == nullptr)
{
head == cur;
}
else
{
cur->next = head;
head = cur;
}
size++;
}
V pop()
{
V ans = nullptr;
if (head != null)
{
ans = head->val;
head = head->next;
size--;
}
return ans;
}
};
七.用双链表实现双端队列
直接转载另一个哥们写的,链表主要考察的是coding能力
八.K个节点组内逆序调整问题(leetcode 第25题 hard)
链表的题,想不明白的话先在纸上推演好流程再写,啥都不清楚写个der。。
这个函数是一个换头函数,肯定不是void类型的
可以先组内逆序,在组间链接,不够一组的直接连接。
/**
* Definition for singly-linked list.
* 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) {}
* };
*/
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k)
{
ListNode* start=head;
ListNode* end=getKGroupEnd(start,k);
if(end==nullptr)//不够一组的时候这样
{
return head;
}
//第一组凑齐了
head=end;//先把头给输出了,因为不管怎么样,结果的链表头一定是这个
reverse(start,end);
//上一组的结尾结点
ListNode* lastEnd=start;
while(lastEnd->next!=nullptr)
{
start=lastEnd->next;
end=getKGroupEnd(start,k);
if(end==nullptr)
{
return head;
}
reverse(start,end);
lastEnd->next=end;
lastEnd=start;
}
return head;
}
ListNode* getKGroupEnd(ListNode* start,int k)
{
while(--k!=0&&start!=nullptr)
{
start=start->next;
}
return start;
}
void reverse(ListNode* start,ListNode* end)
{
end=end->next;
ListNode* pre=nullptr;
ListNode* head=start;
ListNode* next=nullptr;
while(head!=end)
{
next=head->next;
head->next=pre;
pre=head;
head=next;
}
start->next=end;
}
};
九.两个链表相加问题
给定两个链表的头节点head1和head2,
认为从左到右是某个数字从低位到高位,返回相加之后的链表
/**
* Definition for singly-linked list.
* 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) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2)
{
int len1=listLength(l1);
int len2=listLength(l2);
ListNode* l=len1>=len2?l1:l2;//l为长链表
ListNode* s=len1>=len2?l2:l1;//s为短链表
ListNode* curL=l;//初始位置都指向头部
ListNode* curS=s;//初始位置都指向头部
ListNode* last=curL;//写入位置
int carry=0;//进位
int curNum=0;//当前数据
while(curS!=nullptr)
{
curNum=curL->val+curS->val+carry;
curL->val = (curNum%10);
carry=curNum/10;
last=curL;
curL=curL->next;
curS=curS->next;
}
while(curL!=nullptr)
{
curNum=curL->val+carry;
curL->val=(curNum%10);
carry=curNum/10;
last=curL;
curL=curL->next;
}
if(carry!=0)
{
last->next=new ListNode(1);
}
return l;
}
//求链表长度
int listLength(ListNode* head)
{
int len=0;
while(head!=nullptr)
{
len++;
head=head->next;
}
return len;
}
};
十.两个有序链表合并
/**
* Definition for singly-linked list.
* 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) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2)
{
if(list1==nullptr||list2==nullptr)
{
return list1==nullptr?list2:list1;
}
ListNode* head=list1->val<=list2->val?list1:list2;
ListNode* cur1=head->next;
ListNode* cur2=list1->val>list2->val?list1:list2;
ListNode* pre=head;
while(cur1!=nullptr&&cur2!=nullptr)
{
if(cur1->val<=cur2->val)
{
pre->next=cur1;
cur1=cur1->next;
}
else
{
pre->next=cur2;
cur2=cur2->next;
}
pre=pre->next;
}
pre->next=cur1!=nullptr?cur1:cur2;
return head;
}
};