真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Java棧和隊(duì)列怎么應(yīng)用

這篇“Java棧和隊(duì)列怎么應(yīng)用”文章的知識(shí)點(diǎn)大部分人都不太理解,所以小編給大家總結(jié)了以下內(nèi)容,內(nèi)容詳細(xì),步驟清晰,具有一定的借鑒價(jià)值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來(lái)看看這篇“Java棧和隊(duì)列怎么應(yīng)用”文章吧。

讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛。我們立志把好的技術(shù)通過(guò)有效、簡(jiǎn)單的方式提供給客戶,將通過(guò)不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:空間域名、虛擬主機(jī)、營(yíng)銷軟件、網(wǎng)站建設(shè)、高明網(wǎng)站維護(hù)、網(wǎng)站推廣。

Java棧和隊(duì)列怎么應(yīng)用

在學(xué)習(xí)棧和隊(duì)列 之前,先了解一下什么是線性表:一次保存單個(gè)同類型的元素,多個(gè)元素之間邏輯上連續(xù),比如數(shù)組,鏈表,字符串,棧和隊(duì)列
棧和隊(duì)列其實(shí)操作受限的線性表,數(shù)組也罷,鏈表也罷,既可以在頭部插入和刪除,也能在尾部插入和刪除,但是棧和隊(duì)列只能在一端插入,在一端刪除

一、棧

1.定義

只能在一端插入元素,也只能在這一端刪除元素(棧頂),可以把棧看作一個(gè)“水杯”,只能從一端添加元素,也只能從一段刪除元素,而且,先進(jìn)入水杯的水在杯底,后進(jìn)入水杯的水在杯頂,往出倒水的時(shí)候,也是倒出的杯頂?shù)乃?,棧也是一樣,先入棧的元素在棧底,后入棧的元素在棧頂,所以先入棧的元素后出,后入棧的元素先出,這也是棧的特性“先進(jìn)后出,后進(jìn)先出”Last In First Out(LIFO),取出元素和添加元素只能在棧頂。
將1 2 3 4 5,一次放入棧中
Java棧和隊(duì)列怎么應(yīng)用

2.棧的應(yīng)用

1.無(wú)處不在的undo(撤銷)操作

在任何一個(gè)編輯器中輸錯(cuò)一個(gè)內(nèi)容后,使用Ctrl + z就返回到了輸入的內(nèi)容;
在任何一個(gè)瀏覽器中點(diǎn)擊后退操作
Java棧和隊(duì)列怎么應(yīng)用
都是棧的這個(gè)結(jié)構(gòu)的應(yīng)用
1.使用編輯器使用撤銷操作,一次輸入就把內(nèi)容壓入棧中,再輸入就就再壓入棧中,發(fā)現(xiàn)一次輸入錯(cuò)誤,就使用撤銷操作,把當(dāng)前棧頂?shù)腻e(cuò)誤內(nèi)容彈出,那么當(dāng)前棧頂?shù)膬?nèi)容就是上次輸入的內(nèi)容。
2.瀏覽網(wǎng)頁(yè)其實(shí)也是相同原理的,就像打開百度 -> 打開csdn -> 打開創(chuàng)作中心,也是使用棧這個(gè)結(jié)構(gòu),先把百度網(wǎng)頁(yè)壓入棧中 ,然后csdn網(wǎng)頁(yè)壓入棧中,然后創(chuàng)作中心網(wǎng)頁(yè)壓入棧中,想要返回到csdn主頁(yè),按下后頭箭頭,就把當(dāng)前棧頂?shù)膭?chuàng)作中心網(wǎng)頁(yè)彈出,取出csdn主頁(yè)。

2.操作系統(tǒng)棧

程序再執(zhí)行的過(guò)程中,從A函數(shù)調(diào)用B函數(shù),從B函數(shù)調(diào)用C函數(shù),調(diào)用結(jié)束,返回執(zhí)行時(shí),如何得知從哪繼續(xù)開始執(zhí)行呢,背后也是棧這個(gè)結(jié)構(gòu)

3.棧的實(shí)現(xiàn)

基于鏈表實(shí)現(xiàn)的棧 – 鏈?zhǔn)綏?br/>基于數(shù)組實(shí)現(xiàn)的棧 – 順序棧(使用較多)
定義一個(gè)基于動(dòng)態(tài)數(shù)組實(shí)現(xiàn)的棧

//基于動(dòng)態(tài)數(shù)組實(shí)現(xiàn)的順序棧public class MyStack {
    //記錄當(dāng)前棧的元素個(gè)數(shù)
    private int size;
    //實(shí)際存儲(chǔ)數(shù)據(jù)的動(dòng)態(tài)數(shù)組,此時(shí)在棧中只能在數(shù)組的尾部添加和刪除元素
    private List data = new ArrayList<>();
    }

4.棧的操作

1.向棧中添加一個(gè)元素
只能在棧頂添加

 /**
     * 向當(dāng)前棧中添加元素 -- >壓棧操作
     * @param val
     */
    public void push(E val){
        data.add(val);
        size++;
    }

2.當(dāng)前從棧頂彈出一個(gè)元素

/**
     * 彈出當(dāng)前棧頂元素,返回棧頂元素的值
     * @return
     */
    public E pop(){
        if (isEmpty()){
            //棧為空無(wú)法彈出
            throw new NoSuchElementException("stack is empty!cannot pop!");
        }
        //在數(shù)組末尾刪除元素
        E val = data.get(size - 1);
        data.remove(size - 1);
        size --;
        return val;
    }

3.查看當(dāng)前棧頂元素,但不彈出

/**
     * 查看當(dāng)前棧頂元素值,不彈出該元素
     * @return
     */
    public E peek(){
        if (isEmpty()){
            throw new NoSuchElementException("stack is empty!cannot peek!");
        }
        return data.get(size - 1);
    }

二、隊(duì)列

1.定義

隊(duì)列:先進(jìn)先出(FIFO)的數(shù)據(jù)結(jié)構(gòu)i,元素只能從隊(duì)尾添加到隊(duì)列中,也只能從隊(duì)首出隊(duì)列,元素的出隊(duì)順序和入隊(duì)順序保持一致
將1 2 3 4 5依次入隊(duì)
Java棧和隊(duì)列怎么應(yīng)用

2.隊(duì)列的應(yīng)用

現(xiàn)實(shí)生活中,各種各樣的“排隊(duì)”操作

3.隊(duì)列的實(shí)現(xiàn)

基于數(shù)組實(shí)現(xiàn)的隊(duì)列 – 順序隊(duì)列
基于鏈表實(shí)現(xiàn)的隊(duì)列 – 鏈?zhǔn)疥?duì)列
出隊(duì)操作只能在隊(duì)列的頭部進(jìn)行,若采用數(shù)組實(shí)現(xiàn)的隊(duì)列,每次出隊(duì)一個(gè)元素就得搬移剩下的所有元素向前移動(dòng)一個(gè)單位,此時(shí)采用鏈表實(shí)現(xiàn)的隊(duì)列更適合隊(duì)列的結(jié)構(gòu),刪除元素只需要?jiǎng)h除頭結(jié)點(diǎn),添加元素在鏈表的尾部添加

public interface Queue {
    //入隊(duì)操作
    void offer(E val);
    //出隊(duì)操作
    E poll();
    //查看隊(duì)首元素
    E peek();
    boolean isEmpty();}

對(duì)于棧來(lái)說(shuō)隊(duì)列的實(shí)現(xiàn)子類是比較多的,比如
FIFO隊(duì)列
雙端隊(duì)列
循環(huán)隊(duì)列
優(yōu)先級(jí)隊(duì)列
不管哪個(gè)隊(duì)列都要實(shí)現(xiàn)

4.FIFO隊(duì)列

1.定義一個(gè)FIFO隊(duì)列

// An highlighted blockvar foo = 'bar';

2.向隊(duì)列中添加一個(gè)元素

public void offer(E val) {
        Node node = new Node<>(val);
        if (head == null){
            head = tail = node;
        }else{
            //鏈表的尾插
            tail.next = node;
            tail = node;
        }
        size++;
    }

3.從當(dāng)前隊(duì)首出隊(duì)一個(gè)元素

 public E poll() {
        if (isEmpty()){
            throw new NoSuchElementException("queue is empty! cannot poll!");
        }
        //頭刪
        E val = head.val;
        Node node = head;
        head = head.next;
        node.next = node = null;
        size--;
        return val;
    }

4.查看當(dāng)前隊(duì)列的隊(duì)首元素

public E peek() {
        if (isEmpty()){
            throw new NoSuchElementException("queue is empty!cannot peek!");
        }
        return head.val;
    }

5.循環(huán)隊(duì)列

1.定義:基本上都是使用固定長(zhǎng)度的數(shù)組來(lái)實(shí)現(xiàn),數(shù)組在實(shí)現(xiàn)隊(duì)時(shí),若從數(shù)組頭部刪除元素需要頻繁的移動(dòng)后面的元素,效率比較低;出隊(duì)和入隊(duì)操作,使用兩個(gè)引用,一個(gè)head,一個(gè)tail,添加元素在數(shù)組的尾部添加,刪除元素只需要移動(dòng)head引用指向的地址即可(邏輯刪除)
2.應(yīng)用:操作系統(tǒng)的生產(chǎn)消費(fèi)者模型,MySQL數(shù)據(jù)庫(kù)的InnoDB存儲(chǔ)引擎的redo日志
3.循環(huán)隊(duì)列就是使用長(zhǎng)度固定的數(shù)組來(lái)實(shí)現(xiàn),數(shù)組頭部就是隊(duì)首(head),數(shù)組的尾部就是隊(duì)尾(tail),數(shù)組[head…tail)時(shí)循環(huán)隊(duì)列的有效元素
head永遠(yuǎn)指向循環(huán)隊(duì)列的第一個(gè)元素
tai永遠(yuǎn)指向循環(huán)隊(duì)列有效元素的后一個(gè)位置
Java棧和隊(duì)列怎么應(yīng)用
此時(shí)循環(huán)隊(duì)列的有效元素就為7 9 1兩個(gè)元素
循環(huán)隊(duì)列出隊(duì)一個(gè)元素,就只用讓head引用向后移動(dòng)一個(gè)位置
Java棧和隊(duì)列怎么應(yīng)用
此時(shí)循環(huán)隊(duì)列的有效元素就只有9 和 1 兩個(gè)元素了
再出隊(duì)一個(gè)元素,但此時(shí)head引用已經(jīng)走到末尾了,所謂循環(huán)隊(duì)列就是當(dāng)head或者tail引用走到數(shù)組末尾時(shí),再向后移動(dòng)就是返回?cái)?shù)組頭部的操作,循環(huán)隊(duì)列最大好處就是進(jìn)行元素的刪除的時(shí)候不需要進(jìn)行數(shù)據(jù)的搬移操作,當(dāng)有新的元素添加到隊(duì)列中就會(huì)覆蓋掉原來(lái)的元素,就只需要將tail索引位置覆蓋上新的元素,再讓tail再向后移動(dòng)

當(dāng)隊(duì)列為空時(shí),head == tail

Java棧和隊(duì)列怎么應(yīng)用

當(dāng)隊(duì)列已“滿”時(shí),head == tail

Java棧和隊(duì)列怎么應(yīng)用
循環(huán)隊(duì)列需要注意的關(guān)鍵點(diǎn)
1.因此當(dāng)head 和 tail相等時(shí),沒(méi)法區(qū)分此時(shí)循環(huán)隊(duì)列已滿,還是為空,因此在循環(huán)隊(duì)列中,若(tail + 1) % n == head就認(rèn)為循環(huán)隊(duì)列已滿
Java棧和隊(duì)列怎么應(yīng)用
此時(shí)循環(huán)隊(duì)列就已經(jīng)滿了,在循環(huán)隊(duì)列中就會(huì)浪費(fèi)一個(gè)空間,判斷隊(duì)列是否已滿
2.head和tail的移動(dòng)不能簡(jiǎn)單的 + 1,使用取模操作,取數(shù)組長(zhǎng)度
tail = (tail + 1) % n
head = (head + 1) % n
對(duì)數(shù)組長(zhǎng)度取模的本質(zhì):
當(dāng)head和tai走到數(shù)組最后一個(gè)索引位置時(shí),下一次要返回?cái)?shù)組頭部,就必須用 + 1對(duì)數(shù)組長(zhǎng)度取模
3.head == tail時(shí),認(rèn)為隊(duì)列為空

6.循環(huán)隊(duì)列的操作

1.定義一個(gè)循環(huán)隊(duì)列

//基于整形的循環(huán)隊(duì)列public class LoopQueue implements Queue {
    //定長(zhǎng)數(shù)組
    private Integer[] data;
    //指向隊(duì)首元素
    int head;
    //指向隊(duì)尾元素的下一個(gè)元素
    int tail;
    public LoopQueue(int size){
        data = new Integer[size + 1];
    }}

2.向循環(huán)隊(duì)列中添加一個(gè)元素

@Override    public void offer(Integer val) {
       if (isFull()){
           throw new ArrayIndexOutOfBoundsException("loopQueue is full!cannot offer");
       }
       data[tail] = val;
       tail = (tail + 1) % data.length;
    }

3.從循環(huán)隊(duì)列中出隊(duì)一個(gè)元素

 @Override    public Integer poll() {
        if (isEmpty()){
            throw new NoSuchElementException("loopQueue is empty!cannot poll!");
        }
        Integer val = data[head];
        head = (head + 1) % data.length;
        return val;
    }

4.查看當(dāng)前循環(huán)隊(duì)列隊(duì)首元素

 @Override    public Integer peek() {
        if (isEmpty()){
            throw new NoSuchElementException("loopQueue is empty!cannot peek!");
        }
        return data[head];
    }

5.判斷當(dāng)前循環(huán)隊(duì)列是否為空

 @Override    public boolean isEmpty() {
        return head == tail;
    }

6.判斷當(dāng)前循環(huán)隊(duì)列是否已滿

 public boolean isFull(){
        return (tail + 1) % data.length == head;
    }

7.toString方法

public String toString(){
        StringBuilder sb = new StringBuilder();
        sb.append("front [");
        //最后一個(gè)有效元素的索引
        int lsatIndex = tail == 0 ? data.length - 1 : tail - 1;
        for (int i = head; i != tail;) {
            sb.append(data[i]);
            if (i != lsatIndex){
                sb.append(", ");
            }
            i = (i + 1) % data.length;
        }
        sb.append("] tail");
        return sb.toString();
    }

7.雙端隊(duì)列

雙端隊(duì)列:Deque是Queue的子接口,這個(gè)隊(duì)列既可以尾插,頭出;也可以頭插,尾出
Java棧和隊(duì)列怎么應(yīng)用
雙端隊(duì)列的一個(gè)常用子類就是LinkedList,不管使用棧還是隊(duì)列,都可以統(tǒng)一使用雙端隊(duì)列接口
1.現(xiàn)在需要一個(gè)棧
Java棧和隊(duì)列怎么應(yīng)用
2.現(xiàn)在需要一個(gè)隊(duì)列
Java棧和隊(duì)列怎么應(yīng)用

以上就是關(guān)于“Java棧和隊(duì)列怎么應(yīng)用”這篇文章的內(nèi)容,相信大家都有了一定的了解,希望小編分享的內(nèi)容對(duì)大家有幫助,若想了解更多相關(guān)的知識(shí)內(nèi)容,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。


文章標(biāo)題:Java棧和隊(duì)列怎么應(yīng)用
URL地址:http://weahome.cn/article/jeghjj.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部