棧與棧的實現(xiàn)

棧是一種基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu)咖摹,只從一端讀寫數(shù)據(jù)柠衍。基本特點就”后進先出“孝赫,例如順序入棧1,2,3,4,5,再順序出棧是5,4,3,2,1

棧的基本操作

棧的基本操作有如下幾種:

  • 檢測棧是否為空
  • 返回棧存儲數(shù)據(jù)的數(shù)量
  • 返回棧頂數(shù)據(jù)/返回棧頂數(shù)據(jù)并將其彈出
  • 將數(shù)據(jù)壓入棧
  • 清空棧

棧的實現(xiàn)

軟件實現(xiàn)——GO語言

軟件的椇旆可以使用鏈表基本結(jié)構(gòu)實現(xiàn)或使用數(shù)組實現(xiàn):使用鏈表棧的優(yōu)勢是棧的容量幾乎不限青柄,確定是入棧出棧都需要開銷較大的聲明結(jié)構(gòu)體;數(shù)組實現(xiàn)的優(yōu)勢是速度快(自增自減一般有指令實現(xiàn))预侯,但是空間必須預(yù)先指定致开。

統(tǒng)一adt接口

type Stack_adt interface {
    Is_empty() bool
    Get_depth() int
    Push(data Stack_data)
    Pop() (Stack_data, error)
    Get_head() (Stack_data, error)
    Clear()
}

鏈表棧

數(shù)據(jù)結(jié)構(gòu)

type stack_node struct {
    data Stack_data
    next *stack_node
}

type Link_stack struct {
    length int
    head   *stack_node
}

判空方法

func (l *Link_stack) Is_empty() bool {
    if l.head.next == nil {
        return true
    } else {
        return false
    }
}

獲取棧中數(shù)據(jù)量方法

func (l *Link_stack) Get_depth() int {
    return l.length
}

壓棧方法

func (l *Link_stack) Push(data Stack_data) {
    new_node := stack_node{data, l.head.next}
    l.head.next = &new_node
    l.length++
}

對于入棧數(shù)據(jù),建立鏈表節(jié)點并將其插入到頭結(jié)點后(讀取位置)萎馅,保證后進先出

彈棧方法

func (l *Link_stack) Pop() (Stack_data, error) {
    if l.Is_empty() {
        return Stack_data{}, errors.New("empty stack")
    } else {
        data := l.head.next.data
        l.head.next = l.head.next.next
        l.length--
        return data, nil
    }
}

直接取出頭結(jié)點后的節(jié)點双戳,若本來就是空棧則返回一個空棧的errors異常,否則該異常為nil

獲取棧頂數(shù)據(jù)(僅獲取糜芳,不彈出)

func (l *Link_stack) Get_head() (Stack_data, error) {
    if l.Is_empty() {
        return Stack_data{}, errors.New("empty stack")
    } else {
        return l.head.next.data, nil
    }
}

與彈棧相同飒货,不同的是讀取后不將讀取的節(jié)點移出鏈表

清空棧

func (l *Link_stack) Clear() {
    _, err := l.Pop()
    for err == nil {
        _, err = l.Pop()
    }
}

不斷彈棧并查看異常(拋棄讀出數(shù)據(jù)),直到報出空棧異常(返回異常不為nil

數(shù)組棧

數(shù)據(jù)結(jié)構(gòu)

const DEPTH = 10

type Array_stack struct {
    data   [DEPTH]Stack_data
    length int
}

data為數(shù)組峭竣,用于存儲數(shù)據(jù)塘辅;length為存入數(shù)據(jù)的數(shù)量,同時也是“棧頂指針”皆撩,標(biāo)記入棧位置

判空方法

func (a *Array_stack) Is_empty() bool {
    if a.length == 0 {
        return true
    } else {
        return false
    }
}

獲取棧中數(shù)據(jù)量方法

func (a *Array_stack) Get_depth() int {
    return a.length
}

壓棧方法

func (a *Array_stack) Push(data Stack_data) {
    if a.length >= DEPTH {
        return
    } else {
        a.data[a.length] = data
        a.length++
    }
}

對于入棧數(shù)據(jù)扣墩,若入棧位置已經(jīng)超出數(shù)組尺寸,則棧滿毅访,不入棧。否則將輸入數(shù)據(jù)插入length標(biāo)記的入棧位置盘榨,并將length自加

彈棧方法

func (a *Array_stack) Pop() (Stack_data, error) {
    if a.length == 0 {
        return Stack_data{}, errors.New("empty stack")
    } else {
        a.length--
        return a.data[a.length], nil
    }
}

先將length自減喻粹,獲得上一個入棧元素的位置,再返回該值

獲取棧頂數(shù)據(jù)(僅獲取草巡,不彈出)

func (a *Array_stack) Get_head() (Stack_data, error) {
    if a.length == 0 {
        return Stack_data{}, errors.New("empty stack")
    } else {
        return a.data[a.length-1], nil
    }
}

與彈棧相同守呜,不同的是讀取后不改變“棧頂指針”的位置

清空棧

func (a *Array_stack) Clear() {
    a.length = 0
}

直接將“棧頂指針”清零即可實現(xiàn)清空棧

切片棧

切片是一種Go語言特有的數(shù)據(jù)結(jié)構(gòu),類似于動態(tài)數(shù)組山憨,使用切片可以實現(xiàn)深度可變的棧查乒。

硬件實現(xiàn)——Verilog語言

module stack_controller #(
    parameter DEPTH_LOG = 4,
    parameter WIDTH = 8
)(
    input clk,    // Clock
    input rst_n,  // Asynchronous reset active low

    input stack_write_req,
    input [WIDTH - 1:0]stack_write_data,
    input stack_read_req,

    output reg stack_empty,
    output stack_full,

    output reg ram_write_req,
    output reg [DEPTH_LOG - 1:0]ram_addr,
    output reg [WIDTH - 1:0]ram_write_data
);

reg [DEPTH_LOG:0]stack_point;
wire is_full = (stack_point == 2 ** DEPTH_LOG)?1'b1:1'b0;
wire is_empty = (stack_point == 'b0)?1'b1:1'b0;
always @ (posedge clk or negedge rst_n) begin //control point of stack
    if(~rst_n) begin
        stack_point <= 'b0;
    end else if(stack_write_req && stack_read_req) begin //lock
        stack_point <= stack_point;
    end else if(stack_write_req && !is_full) begin //write when stack is not full
        stack_point <= stack_point + 1'b1;
    end else if(stack_read_req && !is_empty) begin // read when stack is not empty
        stack_point <= stack_point - 1'b1;
    end
end
assign stack_full = stack_point[DEPTH_LOG];

always @ (posedge clk or negedge rst_n) begin //generate empty signal
    if(~rst_n) begin
        stack_empty <= 'b0;
    end else if(ram_addr == 'b0 && is_empty) begin // delay signal
        stack_empty <= 1'b1;
    end else begin
        stack_empty <= 'b0;
    end
end

always @ (posedge clk or negedge rst_n) begin //generate ram_write_req
    if(~rst_n) begin
        ram_write_req <= 'b0;
    end else if(!is_full) begin
        ram_write_req <= stack_write_req;
    end else begin
        ram_write_req <= 'b0;
    end
end

always @ (posedge clk or negedge rst_n) begin //prepare the addr and data for push
    if(~rst_n) begin
        ram_addr <= 'b0;
        ram_write_data <= stack_write_data;
    end else begin
        ram_addr <= stack_point[DEPTH_LOG - 1:0];
        ram_write_data <= stack_write_data;
    end
end

endmodule

Verilog實現(xiàn)棧的關(guān)鍵點有三個:

  • 控制棧頂指針
  • 棧滿信號生成
  • 棧空信號生成

該硬件棧的棧頂指針指向下一個入棧的位置郁竟,且位數(shù)比ram地址位多一位玛迄,當(dāng)最高位為1時,可認(rèn)為棧溢出棚亩,停止寫入蓖议;同理虏杰,當(dāng)棧頂指針指向0,該棧為空棧勒虾。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末纺阔,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子修然,更是在濱河造成了極大的恐慌笛钝,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件愕宋,死亡現(xiàn)場離奇詭異玻靡,居然都是意外死亡,警方通過查閱死者的電腦和手機掏婶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進店門啃奴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人雄妥,你說我怎么就攤上這事最蕾。” “怎么了老厌?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵瘟则,是天一觀的道長。 經(jīng)常有香客問我枝秤,道長醋拧,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任淀弹,我火速辦了婚禮丹壕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘薇溃。我一直安慰自己菌赖,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布沐序。 她就那樣靜靜地躺著琉用,像睡著了一般。 火紅的嫁衣襯著肌膚如雪策幼。 梳的紋絲不亂的頭發(fā)上邑时,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天,我揣著相機與錄音特姐,去河邊找鬼晶丘。 笑死,一個胖子當(dāng)著我的面吹牛唐含,可吹牛的內(nèi)容都是我干的铣口。 我是一名探鬼主播滤钱,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼脑题!你這毒婦竟也來了件缸?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤叔遂,失蹤者是張志新(化名)和其女友劉穎他炊,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體已艰,經(jīng)...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡痊末,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了哩掺。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凿叠。...
    茶點故事閱讀 40,561評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖嚼吞,靈堂內(nèi)的尸體忽然破棺而出盒件,到底是詐尸還是另有隱情,我是刑警寧澤舱禽,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布炒刁,位于F島的核電站,受9級特大地震影響誊稚,放射性物質(zhì)發(fā)生泄漏翔始。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一里伯、第九天 我趴在偏房一處隱蔽的房頂上張望城瞎。 院中可真熱鬧,春花似錦疾瓮、人聲如沸脖镀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽认然。三九已至补憾,卻和暖如春漫萄,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背盈匾。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工腾务, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人削饵。 一個月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓岩瘦,卻偏偏與公主長得像未巫,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子启昧,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,573評論 2 359

推薦閱讀更多精彩內(nèi)容