鏈表簡介
鏈表是一種動態數據結構,無需知道鏈表的長度,創建鏈表時不分配內存,每當插入一個節點,需要爲新節點分配一次內存,然後調整指針的指向,使得新節點被鏈接到鏈表中。
節點定義:
Struct ListNode
{
Int m_nValue;
ListNode* m_pNext;
};
鏈表操作
注意!!!
1.注意保存頭結點。另新建一個節點來進行數據操作。
2.新建鏈表時,頭結點不存放數據(或存放無意義數據),這種用法經常用到。
3.不使用返回值傳遞而使用參數傳遞時,注意函數內指針的改變不影響函數外的指針,所以參數類型爲指向指針的指針或指向引用的指針。
4.在需要對鏈表進行修改時(包括,添加,刪除等操作),需要對指針進行修改,此時頭結點要單獨拿出來操作(不能使用臨時節點對頭結點進行操作),所以接下來的遍歷對象使用的是ListNode->next;
1.創建節點
ListNode* p = new ListNode();
P->m_nValue = 0;
P->m_pNext = NULL;
2.創建鏈表
3.遍歷鏈表
void travelList(node* pHead)
{
ListNode* pNode = pHead;
If(pHead == NULL){ Return;}
While(pNode != Null)
pNode = pNode->m_pNext;
}
鏈表應用
1.添加節點(使用返回值)
ListNode* addNode(ListNode*head ,int addValue)
{
ListNode* newNode=new node();
newNode->next=NULL;
newNode->value=addValue;
ListNode* p=new node();
p=head; //list的頭結點
if(head==NULL) {
head=newNode; //新節點爲鏈表頭節點
}else {
while(p->next!=NULL)//找到尾節點
p=p->next;
p->next=newNode; //在尾節點後面加入新節點
}
return head;
}
添加節點(使用參數傳遞)
使用參數傳遞時,注意函數內指針的改變不影響函數外的指針,所以參數類型爲指向指針的指針或指向引用的指針。
Void addNode(ListNode** head ,int addValue)
{
ListNode* newNode=new node();
newNode->next=NULL;
newNode->value=addValue;
ListNode* p=new node();
p= *head; //list的頭結點
if(*head==NULL) {
*head=newNode; //新節點爲鏈表頭節點
}else {
while(p->next!=NULL)//找到尾節點
p=p->next;
p->next=newNode; //在尾節點後面加入新節點
}
}
2.刪除節點
ListNode* removeNode(ListNode *head, int value)
{
If(head == NULL){
Return;
}
ListNode *p = head;
If(head->value = value){
Head=head->next;
}Else{
While((p->next!=NULL)&&(p->next->value!=value)){
P = p->next;
}
If((p->next!=NULL)&&(p->next->value==value)){
P->next = p->next->next;
}
}
Return head;
}
3.從尾到頭打印(使用堆棧)
Void travleList(ListNode *head)
{
Std::stack<ListNode *> nodes;
ListNode *p = head;
While(p != NULL){
Nodes.push(p);
P=p->next;
}
While(!nodes.empty()){
P = nodes.top();
Printf(“%d\t”, p->value);
Nodes.pop;
}
}
4. 得到鏈表的倒數第K個節點
最容易想到的當然是先遍歷一次鏈表,得到鏈表的長度n,然後得到鏈表的n-k+1個節點。需要遍歷鏈表兩次,當遇到這種情況,需要考慮只遍歷一次能不能實現。
使用兩個指針構成長度爲K的窗口,進行遍歷。
ListNode * FindTailK(ListNode *head, unsigned int k)
{
If((head == NULL)||(k=0)){
Return NULL;
}
ListNode *pStart = head;
ListNode *pEnd = head;
For(unsigned int i=0; i<k; i++){
If(pEnd->next == NULL){ Return NULL; }
pEnd = pEnd->next;
}
While(pEnd->next != NULL){
pEnd = pEnd->next;
pStart=pStart->next;
}
Return pStart;
}
5.反轉鏈表
爲了保證節點在改變指針指向之後依然可以遍歷接下來的節點,需要定義三個指針,分別指向當前節點,前一個節點和後一個節點。
問題出現了,cur->next 在執行的過程中有修改,所以在迭代的過程中不能使用,需要引入一個臨時變量在cur->next 修改之前進行保存就可以了。
ListNode *ReverseList(ListNode *head)
{
ListNode* CurNode = head;
ListNode* PreNOde = NULL;
ListNode* NextNode = NULL;
ListNode* ReturnNode = NULL:
While(CurNode != NULL){
NextNode = CurNode->Next;
If(NextNode == NULL){
ReturnNode = CurNode;
}
CurNode->next=PreNode;
preNode = CurNode;
CurNode = NextNode;
}
Return ReturnNode;
}
6.鏈表分割
鏈表的分割問題,是先分割,然後再合併。
例如,給定一個鏈表和一個數字x,將小於x的位於鏈表的前面,大於等於x的位於鏈表的後面。
ListNode *Partition(ListNode* head, int x)
{
ListNode left(-1);
ListNode Right(-1);
ListNode *Left_cur = &Left;
ListNode *Right_cur=&Right;
ListNode *Cur = head;
While(Cur!=NULL){
if(Cur->value<x){
Left_cur->next = cur;
Left_cur = Left_cur->next;
}
Else{
Right_cur->next = cur;
Right_cur = Right_cur->next;
}
Cur = Cur->next;
}
Left_cur->next = Right->next;
Ritht_next = null;
Return left;
}
7除去有序鏈表中重複的內容,只留下一個
在鏈表中去掉節點的方式是將next指向next->next
ListNode* deleteDuplicates(ListNode* head) {
if (head == nullptr) return nullptr;
ListNode *cur = head;
ListNode *next=head->next;
while(cur->next!=NULL)
{
if (cur->val == next->val) {
cur->next = next->next;
} else {
cur = cur->next;
}
next = cur->next;
}
return head;
}
8兩個數相加
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
Explanation: 342 + 465 = 807.
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode sum(-1);
ListNode *Cur = ∑
int flag = 0;
int value = 0, a=0, b=0;
while((l1 != NULL)||(l2!= NULL))
{
a = l1 != NULL ? l1->val : 0;
b = l2 != NULL ? l2->val : 0;
value = (a+b+flag)%10;
flag = (a+b+flag)/10;
Cur->next = new ListNode(value);
l1 = l1 != NULL ? l1->next : NULL;
l2 = l2 != NULL ? l2->next : NULL;
Cur = Cur->next;
}
if(flag > 0)
{
Cur->next = new ListNode(flag);
}
return sum.next;
}
9.每相鄰兩個節點交換順序
利用上一步的cur進行迭代。
ListNode* swapPairs(ListNode* head) {
if (head == nullptr || head->next == nullptr) return head;
ListNode result(-1);
result.next = head;
ListNode *pre = &result;
ListNode *cur = pre->next;
ListNode *next = cur->next;
while(next != NULL)
{
pre->next = next;
cur->next = next->next;
next->next = cur;
pre = cur;
cur = cur->next;
next = cur ? cur->next : NULL;
}
return result.next;
}