1. 程式人生 > >堆和棧的基本概念

堆和棧的基本概念

undefined 改變 指向 text 內存 引用 編譯 col 系統

  JS中有基本數據類型和引用數據類型,基本數據類型包括了Number、Boolean、String、Null、Undefined和Symbol這些數據類型,引用數據類型包括了Array、Object等數據類型,基本數據類型存放在棧中,而引用數據類型存放在堆中,那麽對於數據結構中的堆和棧來說,兩者有何區別呢?

  直觀來看,當一個變量存儲數據放在棧中,使用和復制該變量,只是改變了存儲的數據,並沒有影響這個變量,比如:

let a = 1;
let b = a;
b = 2;

  a、b都是數字類型的數據,將a的數據復制給b,是將a存放的1傳遞給b,對b進行操作不會影響到a本身。那麽如果數據是存放在堆中呢?

let arr1 =  [1, 2, 3, 4, 5];
let arr2 = arr1;
arr2[2] = 10;

  列舉兩個數組,將數組1復制給數組2,引用數據是對數組內數據的指向,當改變數組2第三個數時,數組1的第三個數也會被改變。

  在網上常常能看到把堆比喻成一顆倒的樹,將棧比喻成一個箱子。堆(heap)是一種經過排序的樹形數據結構,每個結點都有一個值。堆中某個節點的值總是不大於或不小於其父節點的值。堆總是一棵完全二叉樹。將根節點最大的堆叫做最大堆或大根堆,根節點最小的堆叫做最小堆或小根堆。常見的堆有二叉堆、斐波那契堆等。堆是在程序運行時,而不是在程序編譯時,申請某個大小的內存空間。即動態分配內存,對其訪問和對一般內存的訪問沒有區別。應用程序在運行的時候請求操作系統分配給自己內存,一般是申請/給予的過程。

  棧(stack)又名堆棧,它是一種運算受限的線性表。其限制是僅允許在表的一端進行插入和刪除運算。這一端被稱為棧頂,相對地,把另一端稱為棧底。棧就像一個桶或者箱子,後放進去的先拿出來,它下面本來有的東西要等它出來之後才能出來(先進後出,而堆是先進先出),棧是操作系統在建立某個進程時或者線程(在支持多線程的操作系統中是線程)為這個線程建立的存儲區域,該區域具有FIFO(first-in-first-out)的特性,在編譯的時候可以指定需要的Stack的大小。

  另外有個說法是堆棧,堆棧本身就是棧,只是換了個抽象的名字。堆棧中,最後一個放入堆棧中的物體總是被最先拿出來, 這個特性通常稱為後進先出(LIFO)隊列。 堆棧中定義了一些操作。 兩個最重要的是PUSH和POP。 PUSH操作在堆棧的頂部加入一 個元素。POP操作相反, 在堆棧頂部移去一個元素, 並將堆棧的大小減一。

堆和棧的基本概念