大話數(shù)據(jù)結(jié)構(gòu) - 棧

代碼GitHub地址


棧的分類

  • 棧是特殊的線性表
  • 棧的典型應(yīng)用遞歸籽御,四則運(yùn)算表達(dá)式求值话浇。

棧的分類有兩種:

  • 靜態(tài)棧(數(shù)組實(shí)現(xiàn))
  • 動(dòng)態(tài)棧(鏈表實(shí)現(xiàn))

我們接下來(lái)會(huì)分別實(shí)現(xiàn)這兩種棧增蹭。

棧的操作

數(shù)組方式

代碼GitHub地址 - 歡迎star

棧節(jié)點(diǎn)

public class Node {

    private int value;

    public Node() {

    }

    public Node(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }
}

由于是數(shù)組方式存儲(chǔ)的杆逗,每個(gè)節(jié)點(diǎn)都能方便的存取它的前驅(qū)后繼節(jié)點(diǎn)学少。所以我們聲明的棧節(jié)點(diǎn)只需要存在一個(gè)存值的value屬性即可剪个。

public class Stacks {

    private static final int MAX_SIZE = 100;
    private static final int MIN_SIZE = -1;

    /**
     * 空棧默認(rèn) top = 1
     */
    private int top = -1;
    /**
     * 順序棧默認(rèn)最大 100
     */
    private Node[] nodes = new Node[MAX_SIZE];

    public Stacks() {

    }

    public Stacks(int top) {
        this.top = top;
    }

    public Stacks(Node[] nodes) {
        this.nodes = nodes;
    }

    public Stacks(int top, Node[] nodes) {
        this.top = top;
        this.nodes = nodes;
    }

}

由于是數(shù)組形式聲明的棧,所以我們需要規(guī)定棧最大容量版确,并且設(shè)立top變量來(lái)定位棧頂元素扣囊。

入棧

/**
 * 入棧
 *
 * @param stacks
 * @param value
 * @return
 */
public static int push(Stacks stacks, int value) {
    Node node = new Node(value);
    if (stacks.top == MAX_SIZE) {
        return 0;
    }
    stacks.top++;
    stacks.nodes[stacks.top] = node;
    return 1;
}

很簡(jiǎn)單,只需要注意代碼執(zhí)行順序即可绒疗,需要明白棧頂指針指向棧頂元素侵歇。每次入棧操作執(zhí)行完top必然會(huì)++那么它又需要在入棧后指向最新插入的新元素,就必然在賦值前++,同時(shí)賦值的時(shí)候找數(shù)組的top索引處給就是最方便快捷的吓蘑。

出棧

/**
 * 出棧
 *
 * @param stacks
 * @return
 */
public static int pop(Stacks stacks) {
    if (stacks.top == MIN_SIZE) {
        return 0;
    }
    stacks.nodes[stacks.top] = null; //
    stacks.top--;
    return 1;
}

和入棧操作相反惕虑,需要把棧的top索引處的元素置空,在top還在指向該節(jié)點(diǎn)的時(shí)候置空磨镶,然后top--即可溃蔫。

遍歷

/**
 * 遍歷
 *
 * @param stacks
 */
public static void traverse(Stacks stacks) {
    int top = stacks.top;
    while (top > MIN_SIZE) {
        System.out.println(stacks.nodes[top--].getValue());
    }
}

根據(jù)top從頂?shù)降祝瑥淖畲笾档?遍歷即可琳猫。
需要注意的是:不要直接操作Stack.top變量伟叛,而是把他取出來(lái)?yè)Q其他局部變量操作。否則在你遍歷完之后脐嫂,棧中就真的沒(méi)有元素了痪伦。因?yàn)?code>Stack.top變量已經(jīng)被你指向了棧底。

判斷是否為空

/**
 * 判斷是否為空
 *
 * @param stacks
 * @return
 */
public static boolean isEmpty(Stacks stacks) {
    return stacks.top == MIN_SIZE;
}

清空棧

/**
 * 清空棧
 *
 * @param stacks
 */
public static void clean(Stacks stacks) {
    while (stacks.top > MIN_SIZE) {
        stacks.nodes[stacks.top] = null;
        stacks.top--;
    }
}

也可以循環(huán)調(diào)用出棧(pop)方法雹锣。通過(guò)while循環(huán)來(lái)判斷top變量是否大于0來(lái)判斷是否空棧网沾。

共享?xiàng)?/h3>

共享?xiàng)R话愕氖褂脠?chǎng)景是兩個(gè)棧的空間有相反的需求關(guān)系的時(shí)候。也就是一個(gè)棧增長(zhǎng)的時(shí)候另一個(gè)棧在縮短的情況蕊爵。比如購(gòu)買股票辉哥,有人買入就一定有人賣出,總量放在那里不變。不可能兩面都有人一直買入醋旦,那么棧很快就會(huì)溢出了恒水。所以在使用共享?xiàng)5臅r(shí)候考慮好使用場(chǎng)景是否符合。

public class SharedStack {

    private static final int MAX_SIZE = 100;
    private static final int MIN_SIZE = -1;

    public Node[] stackElement = new Node[MAX_SIZE];
    /**
     * 棧1的棧頂指針初始為-1
     */
    public int top_1 = MIN_SIZE;
    /**
     * 棧2的棧頂指針 初始為n
     */
    public int top_2 = MAX_SIZE;

    public SharedStack() {

    }
    
}

共享?xiàng)?- 入棧

/**
 * 入棧
 *
 * @param stack       棧
 * @param value       插入的元素值
 * @param stackNumber 棧序號(hào)饲齐,棧1钉凌,還是棧2
 * @return 成功與否,失敗0捂人,成功返回插入的值
 */
public static int push(SharedStack stack, int value, int stackNumber) {
    Node newNode = new Node(value);
    if (stack.top_1 + 1 == stack.top_2) {
        return 0;
    }
    if (stackNumber == 1) {
        // 棧1插入元素
        stack.stackElement[++stack.top_1] = newNode;
    } else if (stackNumber == 2) {
        // 棧2插入元素
        stack.top_2--;
        stack.stackElement[--stack.top_2] = newNode;
    }
    return value;
}

共享?xiàng)?- 出棧

/**
 * 出棧
 *
 * @param stack
 * @param stackNumber
 * @return 刪除的棧頂元素的值
 */
public static int pop(SharedStack stack, int stackNumber) {
    int value = 0;
    if (stackNumber == 1) {
        if (stack.top_1 == MIN_SIZE) {
            return 0;
        }
        value = stack.stackElement[stack.top_1--].getValue();
    } else if (stackNumber == 2) {
        if (stack.top_2 == MAX_SIZE) {
            return 0;
        }
        value = stack.stackElement[stack.top_2++].getValue();
    }
    return value;
}

鏈表方式

代碼GitHub地址 - 歡迎star

棧節(jié)點(diǎn)

public class Node {

    private int value;
    private Node nextNode;

    public Node() {
    }

    public Node(int value) {
        this.value = value;
    }

    public Node(Node nextNode) {
        this.nextNode = nextNode;
    }

    public Node(int value, Node nextNode) {
        this.value = value;
        this.nextNode = nextNode;
    }
    
    getter/setter

可以看出相比于數(shù)據(jù)方式御雕,棧節(jié)點(diǎn)多了一個(gè)nextNode指針域。指向它的后繼節(jié)點(diǎn)

public class Stacks {

    /**
     * 棧頂結(jié)點(diǎn)
     */
    private Node topElement;
    /**
     * 棧底節(jié)點(diǎn)
     */
    private Node bottmElement;

    public Stacks() {

    }

    public Stacks(Node topElement, Node bottmElement) {
        this.topElement = topElement;
        this.bottmElement = bottmElement;
    }

}

此時(shí)棧如果是空棧的話topElement = bottmElement

入棧

/**
 * 入棧
 *
 * @param stacks
 * @param value
 * @return
 */
public static int push(Stacks stacks, int value) {
    Node node = new Node(value);
    // 下一節(jié)點(diǎn)為根節(jié)點(diǎn)
    node.setNextNode(stacks.topElement);
    stacks.topElement = node;
    return 1;
}

需要記住的一個(gè)思路就是滥搭,新插入節(jié)點(diǎn)的后繼節(jié)點(diǎn)是當(dāng)前棧的棧頂元素酸纲。插入之后才能移動(dòng)該棧頂元素的指針topElement

出棧

/**
 * 出棧
 *
 * @param stacks
 * @return
 */
public static int pop(Stacks stacks) {
    if (stacks.topElement == stacks.bottmElement) {
        return 0;
    }
    stacks.topElement = stacks.topElement.getNextNode();
    return 1;
}

棧頂指針指向其后繼節(jié)點(diǎn)即可瑟匆。

遍歷

/**
 * 遍歷
 *
 * @param stacks
 */
public static void traverse(Stacks stacks) {
    Node node = stacks.topElement;
    while (node != stacks.bottmElement) {
        System.out.println(node.getValue());
        node = node.getNextNode();
    }
}

換一個(gè)節(jié)點(diǎn)指向當(dāng)前棧頂節(jié)點(diǎn)的節(jié)點(diǎn)即可闽坡。然后一直遍歷輸出到棧底節(jié)點(diǎn)為止。

判斷是否為空

/**
 * 判斷是否為空
 *
 * @param stacks
 * @return
 */
public static boolean isEmpty(Stacks stacks) {
    return stacks.topElement == stacks.bottmElement;
}

清空

/**
 * 清空
 *
 * @param stacks
 */
public static void clean(Stacks stacks) {
    stacks.bottmElement = null;
    stacks.topElement = stacks.bottmElement;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末愁溜,一起剝皮案震驚了整個(gè)濱河市疾嗅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌冕象,老刑警劉巖宪迟,帶你破解...
    沈念sama閱讀 212,185評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異交惯,居然都是意外死亡次泽,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,445評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門席爽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)意荤,“玉大人,你說(shuō)我怎么就攤上這事只锻【料瘢” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 157,684評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵齐饮,是天一觀的道長(zhǎng)捐寥。 經(jīng)常有香客問(wèn)我,道長(zhǎng)祖驱,這世上最難降的妖魔是什么握恳? 我笑而不...
    開(kāi)封第一講書人閱讀 56,564評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮捺僻,結(jié)果婚禮上乡洼,老公的妹妹穿的比我還像新娘崇裁。我一直安慰自己,他們只是感情好束昵,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,681評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布拔稳。 她就那樣靜靜地躺著,像睡著了一般锹雏。 火紅的嫁衣襯著肌膚如雪巴比。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,874評(píng)論 1 290
  • 那天礁遵,我揣著相機(jī)與錄音轻绞,去河邊找鬼。 笑死榛丢,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的挺庞。 我是一名探鬼主播晰赞,決...
    沈念sama閱讀 39,025評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼选侨!你這毒婦竟也來(lái)了掖鱼?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 37,761評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤援制,失蹤者是張志新(化名)和其女友劉穎戏挡,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體晨仑,經(jīng)...
    沈念sama閱讀 44,217評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡褐墅,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,545評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了洪己。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片妥凳。...
    茶點(diǎn)故事閱讀 38,694評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖答捕,靈堂內(nèi)的尸體忽然破棺而出逝钥,到底是詐尸還是另有隱情,我是刑警寧澤拱镐,帶...
    沈念sama閱讀 34,351評(píng)論 4 332
  • 正文 年R本政府宣布艘款,位于F島的核電站,受9級(jí)特大地震影響沃琅,放射性物質(zhì)發(fā)生泄漏哗咆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,988評(píng)論 3 315
  • 文/蒙蒙 一益眉、第九天 我趴在偏房一處隱蔽的房頂上張望岳枷。 院中可真熱鬧,春花似錦、人聲如沸空繁。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,778評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)盛泡。三九已至闷祥,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間傲诵,已是汗流浹背凯砍。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,007評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拴竹,地道東北人悟衩。 一個(gè)月前我還...
    沈念sama閱讀 46,427評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像栓拜,于是被迫代替她去往敵國(guó)和親座泳。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,580評(píng)論 2 349

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