第3章“棧”
數組是計算機科學中最常用的數據結構,上一章我們學習瞭如何創建和使用它。我們知道,
可以在數組的任意位置上刪除或添加元素。然而,有時候我們還需要一種在添加或刪除元素時有
更多控制的數據結構。有兩種數據結構類似於數組,但在添加和刪除元素時更爲可控。它們就是棧和隊列
棧是一種遵從後進先出(LIFO—Last-In-First-Out)原則的有序集合。新添加的或待刪除的元素都保存在棧的末尾,稱作棧頂,另一端就叫棧底。在棧裏,新元素都靠近棧頂,舊元素都接近棧底
棧也被用在編程語言的編譯器和內存中保存變量、方法調用等
一.棧的創建
- 我們將創建一個類來表示棧。讓我們從基礎開始,先聲明這個類:
//先聲明這個類:
function Stack() {
//1.各種屬性和方法的聲明
var items = [];//1.1需要一種數據結構來保存棧裏的元素。可以選擇數組
// 1.2接下來,要爲我們的棧聲明一些方法
}
- 我們的棧聲明一些方法。
push(element(s)) :添加一個(或幾個)新元素到棧頂。
pop() :移除棧頂的元素,同時返回被移除的元素。
peek() :返回棧頂的元素,不對棧做任何修改(這個方法不會移除棧頂的元素,僅僅返
回它)。
isEmpty() :如果棧裏沒有任何元素就返回 true ,否則返回 false 。
clear() :移除棧裏的所有元素。
size() :返回棧裏的元素個數。這個方法和數組的 length 屬性很類似 - 實現push方法
這個方法負責往棧裏添加新元素,
有一點很重要:該方法只添加元素到棧頂,也就是棧的末尾
function Stack() {
//1.各種屬性和方法的聲明
var items = [];//1.1需要一種數據結構來保存棧裏的元素。可以選擇數組
// 1.2接下來,要爲我們的棧聲明一些方法
this.push = function(element){
items.push(element);
console.log(items);
};
}
//測試類
var s =new Stack();
s.push("aa");
s.push("bb");
- 實現 pop 方法
這個方法主要用來移除棧裏的元素。棧遵從LIFO原則,因此移
出的是最後添加進去的元素
function Stack() {
//1.各種屬性和方法的聲明
var items = [];//1.1需要一種數據結構來保存棧裏的元素。可以選擇數組
// 1.2接下來,要爲我們的棧聲明一些方法
this.push = function(element){
items.push(element);
console.log(items);
};
this.pop = function(){
return items.pop();
};
}
//測試類
var s =new Stack();//測試push
s.push("aa");
s.push("bb");
var popped = s.pop();
console.log(popped);//bb展示要刪除的元素是什麼
- 只能用 push 和 pop 方法添加和刪除棧中元素,這樣一來,我們的棧自然就遵從了LIFO原則
- 爲我們的類實現一些額外的輔助方法。如果想知道棧裏最後添加的元素是什麼,可以用 peek 方法。這個方法將返回棧頂的元素:
因爲類內部是用數組保存元素的,所以訪問數組的最後一個元素可以用 length - 1 :
function Stack() {
//1.各種屬性和方法的聲明
var items = [];//1.1需要一種數據結構來保存棧裏的元素。可以選擇數組
// 1.2接下來,要爲我們的棧聲明一些方法
this.push = function(element){
items.push(element);
console.log(items);
};
this.peek = function(){
return items[items.length-1];
};
}
//測試類
var s =new Stack();//測試push
s.push("aa");
s.push("bb");
var peeked = s.peek();
console.log(peeked);//bb
- 輔助方法:isEmpty ,如果棧爲空的話將返回 true ,否則就返回 false :
使用 isEmpty 方法,我們能簡單地判斷內部數組的長度是否爲0。
function Stack() {
//1.各種屬性和方法的聲明
var items = [];//1.1需要一種數據結構來保存棧裏的元素。可以選擇數組
// 1.2接下來,要爲我們的棧聲明一些方法
this.push = function(element){
items.push(element);
console.log(items);
};
this.isEmpty = function(){
return items.length == 0;
};
}
//測試類
var s =new Stack();//測試push
s.push("aa");
s.push("bb");
var isEmptyed = s.isEmpty();
console.log(isEmptyed);//false
- 類似於數組的 length 屬性,我們也能實現棧的 length 。對於集合,最好用 size 代替 length 。
因爲棧的內部使用數組保存元素,所以能簡單地返回棧的長度:
function Stack() {
//1.各種屬性和方法的聲明
var items = [];//1.1需要一種數據結構來保存棧裏的元素。可以選擇數組
// 1.2接下來,要爲我們的棧聲明一些方法
this.push = function(element){
items.push(element);
console.log(items);
};
this.size = function(){
return items.length;
};
}
//測試類
var s =new Stack();//測試push
s.push("aa");
s.push("bb");
var sizeed=s.size();
console.log(sizeed);//2
- clear 方法 clear 方法用來移除棧裏所有的元素,把棧清空。實現這個
方法最簡單的方式是
function Stack() {
//1.各種屬性和方法的聲明
var items = [];//1.1需要一種數據結構來保存棧裏的元素。可以選擇數組
// 1.2接下來,要爲我們的棧聲明一些方法
this.push = function(element){
items.push(element);
console.log(items);
};
this.size = function(){
return items.length;
};
this.clear = function(){
items = [];
};
}
//測試類
var s =new Stack();//測試push
s.push("aa");
s.push("bb");
var isclear = s.clear();
var sizeed=s.size();
console.log(sizeed);//2
清空棧還可以:多次調用 pop 方法,把數組中的元素全部移除,這樣也能實現 clear 方法
- 輔助方法:print 它會把棧裏的元素都輸出到控制檯:
this.print = function(){
console.log(items.toString());
};
以上的push和pop還有幾個輔助方法完成“創建棧”
- 棧的全部代碼
function Stack() {
var items = [];
this.push = function(element){
items.push(element);
};
this.pop = function(){
return items.pop();
};
this.peek = function(){
return items[items.length-1];
};
this.isEmpty = function(){
return items.length == 0;
};
this.size = function(){
return items.length;
};
this.clear = function(){
items = [];
};
this.print = function(){
console.log(items.toString());
};
}
- 使用 Stack 類
首先,我們需要初始化 Stack 類。然後,驗證一下棧是否爲空(輸出是 true ,因爲還沒有往棧裏添加元素)。
function Stack() {
var items = [];
this.isEmpty = function(){
return items.length == 0;
};
}
var stack =new Stack();//
console.log(stack.isEmpty());//true
function Stack() {
var items = [];
// 判斷棧是否爲空
this.isEmpty = function(){
return items.length == 0;
};
// 往棧裏添加的元素
this.push = function(element){
items.push(element);
console.log(items)
};
// 往棧裏添加的最後一個元素
this.peek = function(){
return items[items.length-1];
};
// 棧裏有多少個元素
this.size = function(){
return items.length;
};
// 移除
this.pop = function(){
return items.pop();
};
// 打印棧現在的元素有哪些
this.print = function(){
console.log(items.toString());
};
}
var stack =new Stack();//
console.log(stack.isEmpty());//true
stack.push(5);
stack.push(8);
console.log(stack.peek());//輸出8.因爲它是往棧裏添加的最後一個元素
stack.push(11);
console.log(stack.size());//3
console.log(stack.isEmpty()); //輸出false
stack.pop();
console.log(stack.size()); //輸出2
stack.print();//5,8
二.從十進制到二進制(棧的應用)
- 十進制轉成二進制
function ten2two(num) {
let rem , arr = [],res = '';
while(num){
rem = num % 2;
arr.push(rem);
num = Math.floor(num/2);
}
while(arr.length) {
res += arr.pop();
}
return res;
}
console.log(ten2two(10));//1010
- 十進制轉任意進制
//十進制轉化爲任意進制
function transfer1(num,base) {
return num.toString(base);
}
console.log(transfer1(10,2));//1010
console.log(transfer1(10,8));//12
function transfer2(num,base) {
let arr = [],res = '',rem,digits = '0123456789ABCDEF';
while(num){
rem = num % base;
arr.push(rem);
num = Math.floor(num/base);
}
while(arr.length) {
res += digits[arr.pop()];
}
return res;
}
console.log(transfer2(10,2));//1010
console.log(transfer2(10,8));//12