摘要:性質(zhì)相對(duì)于數(shù)組,長(zhǎng)度可變插入刪除更容易。為了正確的反轉(zhuǎn)一個(gè)鏈表,需要調(diào)整鏈表中指針的方向指針?lè)聪颉W⒁猓趩捂湵碇校瑢⒁粋€(gè)節(jié)點(diǎn)的指向后繼的指針指向它的前驅(qū),將會(huì)導(dǎo)致鏈表的斷裂。
雖是讀書(shū)筆記,但是如轉(zhuǎn)載請(qǐng)注明出處 http://segmentfault.com/blog/exploring/
.. 拒絕伸手復(fù)制黨
以下是算法導(dǎo)論第十章的學(xué)習(xí)筆記
1 棧棧頂指針 top (初始值top = -1)指向棧頂元素,插入時(shí)先修改指針再插入,刪除時(shí)先取棧頂元素再修改指針.
1.1 性質(zhì)后進(jìn)先出
入棧,出棧都是O(1)
javapublic class Stack { private int[] array = new int[5]; private int top = -1; public Boolean stackempty(){ if(top == -1){ return true; } else return false; } public void push(int x){ if(top<=array.length-1){ array[++top] = x; } else{ System.out.println("overflow"); } }
java public int pop() { int number = -1; if(stackempty() != true){ number = array[top]; top--; return number; } else { System.out.println("underflow"); return -1; } }2 隊(duì)列
用array[n]數(shù)組實(shí)現(xiàn)的至多含有n-1個(gè)元素的隊(duì)列的方法.
隊(duì)列具有屬性head[Q],指向隊(duì)列的頭. 屬性tail[Q]指向新元素要被插入的地方
head[Q] = tail[Q]時(shí),隊(duì)列空;
head[Q] = tail[Q]+1時(shí),隊(duì)列滿;
初始head[Q] = tail[Q] = 1
先進(jìn)先出
入隊(duì),出隊(duì)都是O(1)
javapublic class Queue { private int[] array = new int[4]; private int head = 1; private int tail = 1; //入隊(duì) public void enqueue(int x){ //處理上溢 try{ if(head != tail +1){ array[tail++] = x; if(tail == array.length){ tail = 0; } } else{ System.out.println("overflow"); throw new Exception("queue overflow"); } }catch(Exception e){ e.printStackTrace(); } }
java //出隊(duì) public int dequeue(){ int number=0; try{ if(tail != head){ number = array[head]; head++; } else{ throw new Exception("queue underflow"); } }catch(Exception e){ System.out.println("underflow"); e.printStackTrace(); } return number; }3. (雙向)鏈表
鏈表是面試時(shí)被頻繁提及的DS。 每個(gè)對(duì)象包括一個(gè)關(guān)鍵字域和兩個(gè)指針域prev,next;
鏈表為什么這么受歡迎?
鏈表是一種動(dòng)態(tài)的數(shù)據(jù)結(jié)構(gòu),其操作需要通過(guò)指針進(jìn)行。鏈表內(nèi)存的分配不是在創(chuàng)建鏈表時(shí)一次性完成,而是每添加一個(gè)節(jié)點(diǎn)就分配一次內(nèi)存。由于沒(méi)有閑置內(nèi)存。他的空間效率比數(shù)組更高。
通過(guò)使用哨兵nil節(jié)點(diǎn)(增加一個(gè)nil節(jié)點(diǎn))可以簡(jiǎn)化邊界條件。
3.1 性質(zhì)相對(duì)于數(shù)組,長(zhǎng)度可變;插入刪除更容易。
3.2核心代碼(單向鏈表)
javapublic class LinkedList { private Node head; private Stack s; LinkedList(){ head = null; s = new Stack(); } private static class Node{ int item; Node next; Node(){ this.item = 0; this.next = null; } Node(int item, Node next){ this.item = item; this.next = next; } } public void insert(int x){ Node node = new Node(x, null); Node p = head; // 注意鏈表為空的時(shí)候的插入 if(head==null){ head = node; } // 尾插法 else{ while(p.next != null){ p = p.next; } p.next = node; } } public void travese(Node head){ Node p = head; while(p!=null){ System.out.println(p.item); p = p.next; } }
(雙向鏈表)
javapublic class DoubleLinkedList { // 哨兵節(jié)點(diǎn)nil(作為表頭指針) private Node nil; // 初始化一個(gè)鏈表 DoubleLinkedList(){ nil = new Node(); nil.next = nil; nil.prev = nil; count = 0; } // 鏈表長(zhǎng)度 private int count; private static class Node{ int item; Node next; Node prev; Node(){ item = 0; next = null; prev = null; } Node(int item, Node next, Node prev){ this.item = item; this.next = next; this.prev = prev; } } //返回當(dāng)前鏈表的長(zhǎng)度 public int length(){ return count; } //獲取value為k的節(jié)點(diǎn) public Node listsearch(int k){ Node result = null; Node head = nil; while(head.next != nil){ if(head.next.item == k){ result = head.next; break; } else head = head.next; } return result; } //插入一個(gè)節(jié)點(diǎn)在隊(duì)首 public void listinsert(Node node){ node.next = nil.next; nil.next.prev = node; nil.next = node; node.prev = nil; count++; } //根據(jù)value刪除一個(gè)節(jié)點(diǎn) public Node listdelete(Node node){ Node head = nil; Node nodetodelete; while(head.next!=nil){ if(head.next.item == node.item){ nodetodelete = head.next; //將要?jiǎng)h除的節(jié)點(diǎn) head.next = nodetodelete.next; nodetodelete.next.prev = head; nodetodelete = null; count--; } else{ head = head.next; } } return node; } //輸出鏈表 public void traverse(){ Node head = nil; while( head.next!= nil){ System.out.println(head.next.item); head = head.next; } }3.3 擴(kuò)展 1. 從尾到頭打印鏈表
題目:輸入一個(gè)鏈表的頭節(jié)點(diǎn),從尾到頭打印出來(lái)每個(gè)節(jié)點(diǎn)的值。
解法:遍歷,每遍歷到的元素存到棧,然后輸出棧即可。
代碼:
java public void reveaseoutput(Node head){ Node p = head; if(p==null){ System.out.println("empty list"); } while(p != null){ s.push(p.item); p = p.next; } while(s.stackempty()!= true){ int n = s.pop(); System.out.println(n); } }2. O(1)時(shí)間刪除鏈表節(jié)點(diǎn)
題目:給定單鏈表的頭指針和一個(gè)節(jié)點(diǎn)指針,O(1)時(shí)間刪除該鏈表節(jié)點(diǎn)
解法:下一個(gè)節(jié)點(diǎn)的內(nèi)容復(fù)制到需要?jiǎng)h除的點(diǎn),即覆蓋。然后刪該店的下一個(gè)節(jié)點(diǎn)。
這里需要考慮兩個(gè)邊界條件,1 要?jiǎng)h除的點(diǎn)位于尾部 2 鏈表只有一個(gè)節(jié)點(diǎn)
要考慮魯棒性。
代碼:
javapublic void deleteNode(Node head, Node pToDeleted){ if(head!=null){ //要?jiǎng)h除的是尾節(jié)點(diǎn) if(pToDeleted.next == null){ //如果要?jiǎng)h除的是鏈表唯一的節(jié)點(diǎn) if(head.next==null){ head = null; System.out.println(head); pToDeleted = null; } else{ Node p = head; while(p.next!=pToDeleted){ p = p.next; } p.next = null; pToDeleted =null; } } //要?jiǎng)h除的不是尾節(jié)點(diǎn),且節(jié)點(diǎn)數(shù)大于1 else{ pToDeleted.item = pToDeleted.next.item; pToDeleted.next = pToDeleted.next.next; pToDeleted = null; } }else{ System.out.println("the linklist is empty"); } }3. 倒數(shù)第k個(gè)節(jié)點(diǎn)
題目:輸入一個(gè)鏈表,輸出該鏈表第倒k個(gè)節(jié)點(diǎn)。(鏈表從1開(kāi)始計(jì)數(shù))
解法:定義兩個(gè)指針,第一個(gè)指針從鏈表的head指針開(kāi)始遍歷,向前走k-1步的時(shí)候,第二個(gè)指針開(kāi)始和它一起走。當(dāng)?shù)谝粋€(gè)指針的next指向null的時(shí)候,第二個(gè)指針指向了倒數(shù)第k個(gè)。(這種一次遍歷,對(duì)時(shí)間要求比較高的程序,就需要借助空間,再開(kāi)辟一個(gè)指針)
要考慮魯棒性。
代碼:
java //遍歷鏈表一次,刪除倒數(shù)第K個(gè)元素 public Node FindKthToTail(Node head, int k){ Node p=head; Node q = head; int i; if(head==null || k==0){ return null; } for(i=0;i5 合并鏈表4. 反轉(zhuǎn)鏈表 public Node reverse(){ Node p = head; try{ if(p!=null){ Node pnext = p.next; p.next = null; while(pnext!= null){ Node r = pnext.next; pnext.next = p; p = pnext; pnext = r; } }else{ throw new Exception("empty list"); } }catch(Exception e){ e.printStackTrace(); }finally{ return p; } }題目:定義一個(gè)函數(shù),輸入鏈表頭節(jié)點(diǎn),反轉(zhuǎn)該鏈表并輸出反轉(zhuǎn)后鏈表的頭節(jié)點(diǎn)。
解法:借助三個(gè)指針,prev, p, next. 避免指針斷裂。
( 為了正確的反轉(zhuǎn)一個(gè)鏈表,需要調(diào)整鏈表中指針的方向【指針?lè)聪颉俊W⒁猓趩捂湵碇校瑢⒁粋€(gè)節(jié)點(diǎn)的指向后繼的指針指向它的前驅(qū),將會(huì)導(dǎo)致鏈表的斷裂。導(dǎo)致無(wú)法在單鏈表中遍歷它的后繼節(jié)點(diǎn),因此,在調(diào)整某一節(jié)點(diǎn)的 next 指針時(shí),需要首先將其的后繼節(jié)點(diǎn)保存下來(lái)。)
代碼:java
題目:輸入兩個(gè)增序的鏈表,合并這兩個(gè)鏈表并使新鏈表仍然增序。
解法:重點(diǎn)強(qiáng)調(diào)魯棒性:兩個(gè)鏈表一個(gè)或者兩個(gè)都是null,兩個(gè)鏈表只有一個(gè)節(jié)點(diǎn)。
代碼:
java public Node merge(Node head1, Node head2){ if(head1 == null) { return head2; } if(head2 == null){ return head1; } else{ Node newhead; Node r; Node p = head1; Node q = head2;
java if(head1.item <= head2.item){ newhead = head1; p = p.next; } else{ newhead = head2; q = q.next; } r = newhead; while(p!=null && q!=null){ if(p.item <= q.item){ r.next = p; p = p.next; r = r.next; } else{ r.next = q; q = q.next; r = r.next; } } if(p!=null){ r.next = p; } if(q!=null){ r.next = q; } return newhead; } }6 復(fù)雜鏈表的復(fù)制
題目:
解法:
代碼:
java //1. 根據(jù)原始鏈表的每個(gè)節(jié)點(diǎn)創(chuàng)建對(duì)應(yīng)的copy節(jié)點(diǎn) public void CloneNode(ComplexNode head){ ComplexNode p = head; while(p!=null){ ComplexNode node = new ComplexNode(p.item,null,null); node.next = p.next; p.next = node; p = node.next; } }
java //2. 設(shè)置復(fù)制出來(lái)的節(jié)點(diǎn)的sibling public void connectsiblingnodes(ComplexNode head){ ComplexNode p = head; while(p!=null){ ComplexNode q = p.next; if(p.sibling!=null) { q.sibling = p.sibling.next; } p = q.next; } }
java //3. 拆分鏈表 public ComplexNode ReconnectNodes(ComplexNode head){ ComplexNode p = head; if(p!=null){ ComplexNode newhead = p.next; ComplexNode q = newhead; while(q.next!=null){ p.next = q.next; p = q.next; q.next = p.next; q = p.next; } return newhead; } else{ return null; } }7 尋找第一個(gè)公共節(jié)點(diǎn)
題目:輸入兩個(gè)鏈表,找出第一個(gè)公共節(jié)點(diǎn)。
解法:Y形
代碼:
java public Node findfirstcommonnode(Node head1, Node head2){ Node p = head1;Node q = head2; int length = int length1 = int length2= 0; while(p!=null){ length1 = length1 + 1; p = p.next; } while(q!=null){ length2 = length2 + 1; q = q.next; } p = head1;q = head2; if(length1>length2){ length = length1 - length2; while(length>0){ p = p.next; length--; } } if(length10){ q = q.next; length--; } } while(p!=null&&q!=null&&p.item != q.item){ p = p.next; q = q.next; } return p; }
想更一進(jìn)步的支持我,請(qǐng)掃描下方的二維碼,你懂的~
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/64294.html
摘要:在改進(jìn)前使用數(shù)組的一個(gè)缺點(diǎn)是必須聲明數(shù)組的大小,所以棧有確定的容量。待解決的問(wèn)題建立一個(gè)能夠增長(zhǎng)或者縮短到任意大小的棧。下邊的圖是觀察時(shí)間開(kāi)銷的另一種方式,表示了入棧操作需要訪問(wèn)數(shù)組的次數(shù)。 前言 上一篇:算法分析下一篇:基本排序 本篇內(nèi)容主要是棧,隊(duì)列 (和包)的基本數(shù)據(jù)類型和數(shù)據(jù)結(jié)構(gòu)文章里頭所有的對(duì)數(shù)函數(shù)都是以 2 為底關(guān)于性能分析,可能還是需要一些數(shù)學(xué)知識(shí),有時(shí)間可以回一下在很多...
摘要:一前言上一篇已經(jīng)講過(guò)了鏈表實(shí)現(xiàn)單向鏈表了,它跟數(shù)組都是線性結(jié)構(gòu)的基礎(chǔ),本文主要講解線性結(jié)構(gòu)的應(yīng)用棧和隊(duì)列如果寫(xiě)錯(cuò)的地方希望大家能夠多多體諒并指正哦,如果有更好的理解的方式也希望能夠在評(píng)論下留言,讓大家學(xué)習(xí)學(xué)習(xí)二數(shù)據(jù)結(jié)構(gòu)棧就是這么簡(jiǎn)單數(shù)據(jù)結(jié)構(gòu) 一、前言 上一篇已經(jīng)講過(guò)了鏈表【Java實(shí)現(xiàn)單向鏈表】了,它跟數(shù)組都是線性結(jié)構(gòu)的基礎(chǔ),本文主要講解線性結(jié)構(gòu)的應(yīng)用:棧和隊(duì)列 如果寫(xiě)錯(cuò)的地方希望大家...
摘要:概述集合類主要有大分支,及。不能保證元素的排列順序,順序有可能發(fā)生變化不是同步的集合元素可以是但只能放入一個(gè)是接口的唯一實(shí)現(xiàn)類,可以確保集合元素處于排序狀態(tài)。如果這兩個(gè)的通過(guò)比較返回,新添加的將覆蓋集合中原有的,但不會(huì)覆蓋。 概述 Java集合類主要有2大分支,Collection及Map。Collection體系如下: https://upload-images.jianshu......
摘要:棧隊(duì)列雙端隊(duì)列都是非常經(jīng)典的數(shù)據(jù)結(jié)構(gòu)。結(jié)合了棧和隊(duì)列的特點(diǎn)。因此,在中,有棧的使用需求時(shí),使用代替。迭代器之前源碼源碼之與字段中分析過(guò),容器的實(shí)現(xiàn)中,所有修改過(guò)容器結(jié)構(gòu)的操作都需要修改字段。 棧、隊(duì)列、雙端隊(duì)列都是非常經(jīng)典的數(shù)據(jù)結(jié)構(gòu)。和鏈表、數(shù)組不同,這三種數(shù)據(jù)結(jié)構(gòu)的抽象層次更高。它只描述了數(shù)據(jù)結(jié)構(gòu)有哪些行為,而并不關(guān)心數(shù)據(jù)結(jié)構(gòu)內(nèi)部用何種思路、方式去組織。本篇博文重點(diǎn)關(guān)注這三種數(shù)據(jù)結(jié)構(gòu)...
摘要:會(huì)死循環(huán),因?yàn)闂?nèi)不會(huì)彈出所以判斷會(huì)一直執(zhí)行。集合用于模擬隊(duì)列這種數(shù)據(jù)結(jié)構(gòu),隊(duì)列通常是指先進(jìn)先出的容器。集合不僅提供了的功能,還提供了雙端隊(duì)列,棧的功能。如果有多個(gè)線程需要訪問(wèn)集合中的元素,需要考慮使用將幾個(gè)包裝成線程安全集合。 List判斷兩個(gè)對(duì)象相等只通過(guò)equals方法比較返回true即可。 public class A { @Override public ...
閱讀 2327·2021-09-26 10:21
閱讀 2805·2021-09-08 09:36
閱讀 3070·2019-08-30 15:56
閱讀 963·2019-08-30 12:57
閱讀 934·2019-08-26 10:39
閱讀 3565·2019-08-23 18:11
閱讀 3086·2019-08-23 17:12
閱讀 1089·2019-08-23 12:18