立刻2021年了線性表你還不知道原理?給老王整的明明白白

以前一直在CSDN發文,忽然在微信發文,好緊張!喜歡能夠關注我哦!歡迎點個在看,點個贊,給點鼓勵哦。web

1、線性表必知必懂的原理

(一)線性表通俗易懂原理

線性表是n個數據元素的有限序列,最經常使用的是鏈式表達,一般也叫作線性鏈表或者鏈表在鏈表中存儲的數據元素也叫作結點,一個結點存儲的就是一條數據記錄微信

每一個結點的結構包括兩個部分:網絡

  • 一、具體的數據值;spa

  • 二、指向下一個結點的指針。.net


在鏈表的最後一個結點,一般會有個頭指針用來指向第一個結點3d



對於鏈表的最後一個結點,因爲在它以後沒有下一個結點,所以它的指針是個空指針指針

假如:小明,小張,小李和小鄭在排隊賣雞翅,可是排隊就是講究先來先買的原則,不能插隊。小明購買雞翅付錢的時候忽然沒錢了,假設小明和小鄭認識,小明須要找到小鄭借錢來付上買雞翅的錢。。。那麼小明想要找到小鄭,就須要先找到他的下一個結點,一看不是小鄭,就繼續下一個結點,直到找到爲止。code


小明是能夠找到小鄭的,可是小鄭就沒法找到小明瞭,也就是說單鏈表反過來查找是不行的,也被稱之爲單向鏈表orm

爲了彌補單向鏈表的不足,咱們能夠對單向鏈表進行改造:對象

對於單向鏈表,把最後一個元素的指針指向第一個元素,就獲得了循環鏈表

這樣小鄭就能夠查找他本身的next結點,就能夠找到小明或者小李等。


因爲單向鏈表一個結點只有指向下一個結點的指針,能夠想象一下,是否是也能夠修改爲每一個結點也指向上一個結點,是否是就能夠找到本身上一個結點的數據了呢。

咱們再增長一個指向上一個結點的指針,這樣就獲得了雙向鏈表



固然了,還有更好的辦法,那就是把循環鏈表雙向鏈表進行結合就獲得了雙向循環鏈表



不論是循環鏈表仍是雙向鏈表,仍是雙向循環鏈表,都是在單向鏈表的基礎上加以改造獲得的,改造後的鏈表在操做某種數據的時候能夠提升必定的效率,因此單向鏈表是基礎。

2、線性表對數據的操做

對數據的操做無非就是對數據的增刪改查。只是不一樣的結構有着不一樣的處理邏輯罷了。

(一)增長操做(老王插隊神操做)

小明、小張、小李、小鄭在排着隊取票,忽然來了一個老王,老王很是的着急,由於老王立刻就要到火車發車的時間了,只好插隊了,此時老王跟後面全部的排隊的人都打了個招呼,而後你們也都贊成他插隊進去,那麼老王就先去取票了,咱們忽略打招呼的過程,重點放在如何插隊


咱們先無論如何插入到鏈表中的,先看圖說話

老王若是想插隊一定插入到小明的後面,由於老王在插隊的過程當中小明此時可能會正在取票呢。

那麼插入老王后的數據就是:


整個插入操做也很是的簡單,只須要讓老王的next指向小張,而後小明再指向老王就ok了。


思考一下????

反過來操做能夠嗎?

小明先指向老王老王的next指向小張

能夠嗎?

答案是不能夠的,這樣的話,小明先指向老王以後,小張以及小張以後的數據會所有丟失的。不信你看:



代碼以下:

1newNode.next = head.next
2head.next = newNode

(二)刪除操做(小明取完票讓位給老王)

老王要想取到票,還欠一點火候,欠什麼呢?須要等待小明取完票,而後離開才能夠的。

那麼就須要小明離開這個鏈表,咱們一般說刪除小明這個結點。


刪除操做也比較簡單,只須要把前一個結點指向後面的後面的這個結點就ok了。

代碼:(直接就能夠忽略小明這個結點)

1head.next=head.next.next;

(三)查找操做

查找操做咱們一般會查兩種,第一種是按照位置的序號,第二種是按照值來查找。

例如:

  • 查找第3個位置的是誰;

  • 查找小張是否還在排隊。

在鏈表中的查找功能是比較弱的,對於鏈表中的查找,惟一的辦法就是一個挨着一個的遍歷去對比,對比較着去查找。

時間複雜度也就是O(N)。

3、單鏈表案例

(一)案例1:反轉鏈表

一、題目描述

反轉一個單鏈表。

示例:

輸入: 1->2->3->4->5->NULL
輸出: 5->4->3->2->1->NULL

來源:力扣(LeetCode)
連接:https://leetcode-cn.com/problems/reverse-linked-list
著做權歸領釦網絡全部。商業轉載請聯繫官方受權,非商業轉載請註明出處。


二、解題思路









三、解題代碼

 1/**
2 * Definition for singly-linked list.
3 * public class ListNode {
4 *     int val;
5 *     ListNode next;
6 *     ListNode(int x) { val = x; }
7 * }
8 */

9class Solution {
10    public ListNode reverseList(ListNode head) {
11
12        if(head==null)
13            return head;
14
15        //定義三個指針暫存後面的或者前面的結點,防止丟失。
16        ListNode curr,prev,next;
17        curr=head;
18        prev=next=null;
19
20        while(curr!=null){
21            next = curr.next;
22            curr.next = prev;
23            prev=curr;
24            curr=next;
25        }
26
27        return prev;       
28    }
29}

若是不明白,能夠本身畫圖來試試。

(二)案例2:找出鏈表的中間節點

一、題目描述

876. 鏈表的中間結點

難度簡單256收藏分享切換爲英文關注反饋

給定一個帶有頭結點 head 的非空單鏈表,返回鏈表的中間結點。

若是有兩個中間結點,則返回第二個中間結點。

示例 1:

1輸入:[1,2,3,4,5]
2輸出:此列表中的結點 3 (序列化形式:[3,4,5])
3返回的結點值爲 3 。 (測評系統對該結點序列化表述是 [3,4,5])。
4注意,咱們返回了一個 ListNode 類型的對象 ans,這樣:
5ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, 以及 ans.next.next.next = NULL.

示例 2:

1輸入:[1,2,3,4,5,6]
2輸出:此列表中的結點 4 (序列化形式:[4,5,6])
3因爲該列表有兩個中間結點,值分別爲 3 和 4,咱們返回第二個結點。

提示:

  • 給定鏈表的結點數介於 1100 之間。

https://leetcode-cn.com/problems/middle-of-the-linked-list/



二、解題思路

思路很簡單,就是利用兩個指針來完成,一個走的比較快的,一個走的比較慢的。

每次快的走2個(next.next),每次慢的走1個節點(next)。

當快等於null時(next.next=null時),中止;

當快的next不爲空時,返回慢的next節點。

當快的next爲空時,返回慢的當前節點。



三、解題代碼

 1 //找出鏈表中間節點
2    static public ListNode middleNode(ListNode head) {
3
4        if(head==null)
5            return head;
6        ListNode fast,//快
7                slow;//慢
8        fast=slow=head;
9
10        while (fast!=null && fast.next!=null && fast.next.next!=null){
11            fast = fast.next.next;
12            slow = slow.next;
13        }
14
15        if(fast.next!=null)
16            return slow.next;
17
18        return slow;
19    }

(三)案例3:判斷鏈表是否有環

一、題目描述

141. 環形鏈表

難度簡單738收藏分享切換爲英文關注反饋

給定一個鏈表,判斷鏈表中是否有環。

爲了表示給定鏈表中的環,咱們使用整數 pos 來表示鏈表尾鏈接到鏈表中的位置(索引從 0 開始)。若是 pos-1,則在該鏈表中沒有環。

示例 1:

1輸入:head = [3,2,0,-4], pos = 1
2輸出:true
3解釋:鏈表中有一個環,其尾部鏈接到第二個節點。


示例 2:

1輸入:head = [1,2], pos = 0
2輸出:true
3解釋:鏈表中有一個環,其尾部鏈接到第一個節點。


示例 3:

1輸入:head = [1], pos = -1
2輸出:false
3解釋:鏈表中沒有環。


進階:

你能用 O(1)(即,常量)內存解決此問題嗎?



二、解題思路

此題也是能夠利用快慢指針來完成的,一樣,快指針一次走兩步,慢指針一次走一步,若是有環的話,快和慢兩個指針遲早會相遇的。那麼若是快指針的val等於慢指針的val那麼直接返回true便可。

三、解題代碼

 1/**
2 * Definition for singly-linked list.
3 * class ListNode {
4 *     int val;
5 *     ListNode next;
6 *     ListNode(int x) {
7 *         val = x;
8 *         next = null;
9 *     }
10 * }
11 */

12public class Solution {
13    public boolean hasCycle(ListNode head) {
14         if(head==null)
15            return false;
16
17        ListNode fast,slow;
18        fast=slow=head;
19        while (fast!=null && fast.next!=null && fast.next.next!=null){
20            fast=fast.next.next;
21            slow=slow.next;
22            if(fast.val==slow.val)
23                return true;
24        }
25
26        return false;
27    }
28}

4、鏈表總結

鏈表對數據的存儲方式是按照順序的存儲。


何時用?

  • 當數據元素不肯定時。

  • 當須要常常進行數據的新增和刪除時。

鏈表的反轉、快慢指針是高效的操做鏈表的主要方法,是必需要掌握的內容。







本文分享自微信公衆號 - TrueDei(monkeystudy)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索