Queue(隊列)-Swift實現(xiàn)與廣度優(yōu)先搜索應(yīng)用

  • 定義

僅可以在隊首進(jìn)行刪除吨艇,隊尾進(jìn)行插入的線性表晒旅,稱為隊列边坤。

  • 特點

先入隊列挺庞,則先刪除(First In First Out),類似Stack

  • 應(yīng)用

鍵盤的輸入輸出
廣度優(yōu)先搜索等算法的實現(xiàn)

  • Swift的實現(xiàn)(普通)

struct Queue<T> {
   //這里可以用鏈表代替
    private var array = Array<T>()

    //判空
    var isEmpty: Bool {
        return array.isEmpty
    }
    //隊列中元素個數(shù)
    var count: Int {
        return array.count
    }
    //查看隊首元素
    var front: T? {
        return array.first
    }
    //入隊
    mutating func enqueque(_ element: T) {
        array.append(element)
    }
    //出隊
    mutating func dequeue() -> T? {
        guard !isEmpty else { return nil }
        return array.removeFirst()
    }
}

現(xiàn)在實現(xiàn)的這個隊列就可以工作了舅踪,但是還有些地方是不太完美的纽甘。

  • 1.當(dāng)enqueue(入隊)操作時,因為是將新的元素加到數(shù)組的尾部抽碌,所以入隊的時間復(fù)雜對為O(1)贷腕。
    原因:在Swift中,在數(shù)組的后面咬展,會預(yù)留出一些空的位置
var queue = Queue<String>()
queue.enqueque("a")
queue.enqueque("b")
queue.enqueque("c")
//實際在數(shù)組中情況為
["a", "b", "c", **,  **, **]
//** 就是預(yù)留出來的內(nèi)存泽裳,以備將來插入新的元素
queue.enqueque("d") 后
// 實際情況為
["a", "b", "c", "d",  **, **]

Array的這種機(jī)制也會有問題,因為在數(shù)組的末端只會預(yù)留少量的位置破婆,當(dāng)最后一個預(yù)留的位置也被插入新的元素后涮总,就需要將整個數(shù)組中的元素一起拷貝,到一個新的擁有更多位置的數(shù)組中祷舀,這時的時間復(fù)雜度為O(n)瀑梗,但是這種情況只是偶爾發(fā)生,所以平均的時間復(fù)雜對還是O(1)裳扯。

  • 2.當(dāng)dequeue(出隊)操作時抛丽,因為是將數(shù)組中的第一個元素刪除,當(dāng)刪除第一個元素后饰豺,數(shù)組中剩余的所有元素都需要向前移動一個位置亿鲜,來填充前面的空白,所以這個時候的時間復(fù)雜度為O(n)冤吨,每當(dāng)dequeue一次后蒿柳,時間復(fù)雜度都為O(n),這種操作效率是很低的漩蟆。

  • Swift的實現(xiàn)(稍高效)

稍稍高效些的隊列的實現(xiàn)辦法有好幾種垒探,比如循環(huán)隊列等,我們介紹一個比循環(huán)隊列實現(xiàn)簡單些的怠李。

  • 思路:不再是每出隊一次圾叼,就將數(shù)組中的元素向前移動,而是等到滿足一定條件后捺癞,才統(tǒng)一的向前移動夷蚊。
  • 代碼
struct Queue<T> {
    private var array = Array<T?>()
    ///用來標(biāo)記隊列的頭位置
    private var headIndex = 0
    //判空
    var isEmpty: Bool {
        return array.isEmpty
    }
    
    //隊列中元素個數(shù)
    var count: Int {
        return array.count
    }
    
    //查看隊首元素
    var front: T? {
        if isEmpty { return nil }
        return array[headIndex]
    }
    
    //入隊
    mutating func enqueque(_ element: T) {
        array.append(element)
    }
    
    //出隊
    mutating func dequeue() -> T? {
        //存在隊首元素
        guard !isEmpty, let firstElement = array[headIndex] else { return nil }
        array[headIndex] = nil
        
        //重新標(biāo)記隊首的位置
        headIndex += 1
        //達(dá)到條件,刪除前面的空位置翘簇,條件可以按照需要進(jìn)行更改
        let percentage = Double(headIndex)/Double(array.count)
        if array.count > 20 && percentage > 0.25 {
            array.removeFirst(headIndex)
            headIndex = 0
        }
        return firstElement
    }
}
  • 廣度優(yōu)先搜索

  • 尋找大兵瑞恩撬码,從下面的人物關(guān)系圖中,最終找到瑞恩的最短路徑


    找瑞恩.png
  • 思路
    -- 先找你直接認(rèn)識的朋友中版保,是否有瑞恩呜笑,有查找完成
    -- 如果在你直接認(rèn)識的朋友中沒有夫否,則在朋友的朋友中查找,直到找到叫胁,或所有人都找過
    -- 關(guān)鍵凰慈,只有你直接認(rèn)識的朋友中找完后,才能去從朋友的朋友中去查找驼鹅,這就需要通過隊列的先進(jìn)先出特性來實現(xiàn)
    -- 記錄查找過的人微谓,防止循環(huán)查找

//通過字典(散列)來記錄整張關(guān)系圖
    var relationGraph: [String: [String]] = {
        var dic: [String: [String]] = ["Me": ["A", "C"]]
        dic["A"] = ["B"]
        dic["C"] = ["B", "D", "Ryan"]
        dic["B"] = ["Ryan"]
        dic["D"] = ["Ryan"]
        return dic
    }()
    //創(chuàng)建一個存儲,朋友及朋友的朋友的隊列
    var queue = Queue<String>()
    //用來記錄已經(jīng)查詢過的人
    var checked = [String]()

    func find(_ name: String) {
        findFromQueue(name)
    }

    //到朋友隊列中找Ryan
    func findFromQueue(_ name: String) {
        while queue.count > 0 {
            guard let person = queue.dequeue() else {
                return print("Can not find \(name)")
            }
            //如果查過則找下一個
            if checked.contains(person) { continue }
            //記錄已經(jīng)查詢過的
            checked.append(person)
            //找到
            if person == name {
                print("Find \(name)")
                break
            //未找到
            }else {
                //將朋友的朋友加入到隊列中
                enQueueFriends(person)
            }
        }
    }
    //將朋友加入到隊列中
    func enQueueFriends(_ name: String) {
        guard let friends = relationGraph[name] else { return }
        let _ = friends.map {
            return queue.enqueque($0)
        }
    }
  • 調(diào)用
//將自己的朋友加入到待查找隊列中
enQueueFriends("Me")
//從自己的朋友及朋友的朋友中尋找Ryan
find("Ryan")
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末输钩,一起剝皮案震驚了整個濱河市豺型,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌买乃,老刑警劉巖姻氨,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異剪验,居然都是意外死亡肴焊,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進(jìn)店門功戚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來娶眷,“玉大人,你說我怎么就攤上這事啸臀〗斐瑁” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵壳咕,是天一觀的道長席揽。 經(jīng)常有香客問我,道長谓厘,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任寸谜,我火速辦了婚禮竟稳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘熊痴。我一直安慰自己他爸,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布果善。 她就那樣靜靜地躺著诊笤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪巾陕。 梳的紋絲不亂的頭發(fā)上讨跟,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天纪他,我揣著相機(jī)與錄音,去河邊找鬼晾匠。 笑死茶袒,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的凉馆。 我是一名探鬼主播薪寓,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼澜共!你這毒婦竟也來了向叉?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤嗦董,失蹤者是張志新(化名)和其女友劉穎植康,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體展懈,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡销睁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了存崖。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片冻记。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖来惧,靈堂內(nèi)的尸體忽然破棺而出冗栗,到底是詐尸還是另有隱情,我是刑警寧澤供搀,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布隅居,位于F島的核電站,受9級特大地震影響葛虐,放射性物質(zhì)發(fā)生泄漏胎源。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一屿脐、第九天 我趴在偏房一處隱蔽的房頂上張望涕蚤。 院中可真熱鬧,春花似錦的诵、人聲如沸万栅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽烦粒。三九已至,卻和暖如春代赁,著一層夾襖步出監(jiān)牢的瞬間扰她,已是汗流浹背兽掰。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留义黎,地道東北人禾进。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像廉涕,于是被迫代替她去往敵國和親泻云。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,901評論 2 345

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

  • 對象 1、用已學(xué)的知識來描述一下對象: 2层释、屬性的增婆瓜、刪、改贡羔、查 對象的屬性廉白,沒定義就訪問時不會報錯,會返回und...
    耦耦閱讀 524評論 0 0
  • 最近乖寒,微博關(guān)注了我喜歡的作者猴蹂。三個是比較知名的小說暢銷書作家分別是唐七,喬夕楣嘁,紅搖磅轻。有一位是大家耳熟能詳?shù)淖骷以娙?..
    LemonTree檸檬樹閱讀 194評論 0 0
  • 我們14號從老家回來了,路上遇到彩虹逐虚。媽媽坐順豐車聋溜,爸爸騎摩托車。 15號陪爺爺檢查叭爱,16號繼續(xù)檢查撮躁,然后爸爸給爺...
    miaoyin閱讀 175評論 0 0
  • 注意:前提已經(jīng)安裝好Oracle8.0的JDK 1、從官方網(wǎng)站找到Tomcat8,下載安裝包涤伐; http://to...
    麥克勞林閱讀 1,374評論 0 2
  • > 這是MrKevin365天寫作計劃第22天的寫作內(nèi)容 我想每個城市都像一個人一樣馒胆,有性格有特點。 如果用一種身...
    MrKevin閱讀 307評論 0 0