“堆”,"棧","堆棧"的區別及部分應用


棧又名堆棧,“堆”和"棧"的概念要從數據結構、內存分配這兩個方面來看。

數據結構中,棧(stack)是一種“后進先出”的存儲結構。第一個進棧的為棧底,最后一個進棧的為棧頂。出棧從棧頂開始順序進行。(我覺得在數據結構中就叫棧,這樣比較清楚)
在實際編程中,可以通過兩種方式來實現:使用數組的形式來實現棧,這種棧也稱為靜態棧;使用鏈表的形式來實現棧,這種棧也稱為動態棧。

堆(heap)是一種特殊的完全二叉樹。其中,節點是從左到右填滿的,並且最后一層的樹葉都在最左邊(即如果一個節點沒有左兒子,那么它一定沒有右兒子);每個節點的值都小於(或者都大於)其子節點的值(最小堆或者最大堆)。
相對於棧的“先進后出”特性,堆則是一種經過排序的樹形數據結構,常用來實現優先隊列等。

內存分配中的堆和棧:

內存分配方式不外乎包含如下三種形式:
1.從靜態存儲區域分配,
2.在棧上分配,
3.從堆上分配,也被稱為動態內存分配。

在java中,每個Java進程對應唯一一個JVM實例,每一個JVM實例唯一對應一個JVM內存堆區。進程所創建的所有類的實例(也就是對象)或數組(指的是數組的本身,不是引用)都放在中,並由該進程所有的線程共享。進程中每一個線程在JVM內存中有一個自己私有的區。雖然Java中所有對象的存儲空間都是在堆中分配的,但是這個對象的引用卻是在棧中分配的,也就是說在建立一個對象時在堆和棧中都分配內存,在堆中分配的內存實際存放這個被創建的對象的本身,而在棧中分配的內存只是存放指向這個堆對象的引用而已。局部變量 new 出來時,在棧空間和堆空間中分配空間,當局部變量生命周期結束后,棧空間立刻被回收,堆空間區域等待GC回收。
堆是程序運行時申請的動態內存,而棧是指一種使用堆的方法(所以棧又名堆棧,我覺得內存分配中叫堆棧比較好)

JVM的內存可分為3個區:堆(heap)、棧(stack)和方法區(method,也叫靜態區)。
堆區:
1.存儲的全部是對象,每個對象都包含一個與之對應的class的信息(class的目的是得到操作指令) ;
2.jvm只有一個堆區(heap),且被所有線程共享,堆中不存放基本類型和對象引用,只存放對象本身和數組本身;
為什么叫“堆”,我覺得,堆區和數據結構中的二叉樹堆的性質有類似的地方,如:內存區域不連續的、可隨意存取的、地址鏈表的遍歷方向是由低地址向高地址進行的等。

棧區:
1.每個線程包含一個棧區,棧中只保存基礎數據類型本身和自定義對象的引用;
2.每個棧中的數據(原始類型和對象引用)都是私有的,其他棧不能訪問;
3.棧分為3個部分:基本類型變量區、執行環境上下文、操作指令區(存放操作指令);
為什么叫“棧”,我覺得,首先這是一塊連續的內存區域(其地址的增長方向是由高向低地址進行的,最大容量一般由系統規定,相對於較小)。另外雖然內存讀取是可以隨意的,但C中在函數調用時,第一個存入的是主函數中函數調用后的下一條指令的地址,然后是函數的各個參數,類似入棧操作,在大多數的C編譯器中,參數是由右往左入棧的,然后是函數中的局部變量。注意靜態變量是不入棧的。
當本次函數調用結束后,清除內存類似出棧,局部變量先出棧,然后是參數,最后指針指向最開始存的地址,也就是主函數中的下一條指令,程序由該點繼續運行。與C不同,Java自動管理棧和堆,程序員不能直接地設置棧或堆。

方法區(靜態區):
1.被所有的線程共享,方法區包含所有的class(class是指類的原始代碼,要創建一個類的對象,首先要把該類的代碼加載到方法區中,並且初始化)和static變量。
2.方法區中包含的都是在整個程序中永遠唯一的元素,如class,static變量。
啟動一個Java進程,這個進程首先會讀取類的類信息存放到方法區中。

“棧”是一個重要的數據結構,“后進先出”這種特性有着廣泛的應用,如遞歸調用、括號匹配等是常用的例子。
OSI模型就是一個七層的協議棧。協議棧是指網絡中各層協議的總和,其形象的反映了一個網絡中數據傳輸的過程:由上層協議到底層協議,再由底層協議到上層協議。

通信協議的知識點下篇再復習。。。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM