以前一直在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,咱們返回第二個結點。
提示:
給定鏈表的結點數介於
1
和100
之間。
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源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。