關(guān)于數(shù)據(jù)結(jié)構(gòu)的一點(diǎn)嘮叨

現(xiàn)在大部分高級(jí)編程語(yǔ)言的標(biāo)準(zhǔn)庫(kù)都會(huì)提供幾種常用的數(shù)據(jù)結(jié)構(gòu),諸如線性表奋献、鏈表健霹、棧、隊(duì)列瓶蚂、哈希表等等糖埋,可以滿足日常開(kāi)發(fā)中的大部分需求,開(kāi)發(fā)人員只要調(diào)用接口就行了窃这。這導(dǎo)致有一些半路出家的程序員覺(jué)得學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)沒(méi)有必要瞳别,更有甚者,不僅自身滿足于成為一個(gè)API Caller杭攻,還對(duì)外大肆宣揚(yáng)底層無(wú)用論祟敛,誤導(dǎo)了一些心存迷茫的初學(xué)者。

其實(shí)哪怕從實(shí)用的角度講兆解,學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)也是非常必要的馆铁。至少了解每種數(shù)據(jù)結(jié)構(gòu)的特性,對(duì)于其優(yōu)缺點(diǎn)和適用場(chǎng)景做到心中有數(shù)锅睛,在使用的時(shí)候才能得心應(yīng)手埠巨。舉個(gè)最簡(jiǎn)單的例子,我們知道線性表中的元素在空間上是連續(xù)的现拒,對(duì)其進(jìn)行查找操作十分方便辣垒,但若是要進(jìn)行插入和刪除操作,則需要移動(dòng)其中的元素印蔬,在數(shù)據(jù)量非常大的時(shí)候效率并不高勋桶;相反,鏈表中的元素是通過(guò)指針相連扛点,在空間上并不連續(xù)哥遮,查找的時(shí)候需要從首元素開(kāi)始通過(guò)指針進(jìn)行,效率并不高陵究,但在插入和刪除時(shí)眠饮,只需要改變目標(biāo)位置的指針即可,并不需要移動(dòng)元素铜邮。所以對(duì)于只需要查詢或修改操作的數(shù)據(jù)當(dāng)然是使用線性表為好仪召,而對(duì)于需要進(jìn)行大量增刪操作的數(shù)據(jù)寨蹋,則使用鏈表為宜,在實(shí)際開(kāi)發(fā)中應(yīng)根據(jù)具體情況進(jìn)行選擇權(quán)衡扔茅。若是對(duì)數(shù)據(jù)結(jié)構(gòu)一無(wú)所知已旧,那寫(xiě)出的代碼質(zhì)量著實(shí)令人堪憂。出來(lái)混召娜,遲早是要還的运褪。

在我的理解中,編程玖瘸,其實(shí)就是個(gè)建模+實(shí)現(xiàn)的過(guò)程〗斩铮現(xiàn)在最主流的編程范式是FP(函數(shù)式編程)和OOP(面向?qū)ο缶幊蹋?dāng)然最流行的還是OOP雅倒,鼓吹的人非常多璃诀,說(shuō)得神乎其神,搞得很多初學(xué)者云里霧里蔑匣,油然而生一股不明覺(jué)厲之情劣欢,忍不住就要頂禮膜拜,我當(dāng)初也是如此裁良,想來(lái)真是不勝唏噓凿将。其實(shí)FP和OOP最根本的區(qū)別在于建模的角度不同,F(xiàn)P是要把現(xiàn)實(shí)問(wèn)題抽象成數(shù)學(xué)模型趴久,只有代入丸相,沒(méi)有賦值,具有引用透明性(簡(jiǎn)單來(lái)說(shuō)就是同樣的輸入會(huì)產(chǎn)生同樣的結(jié)果)彼棍,不產(chǎn)生副作用(副作用主要指改變系統(tǒng)狀態(tài))灭忠。與之相對(duì)的是命令式編程范式,廣泛采用賦值座硕,用數(shù)據(jù)的變化來(lái)模擬真實(shí)世界的狀態(tài)變化弛作。OOP是命令式編程的一種,它直觀地將現(xiàn)實(shí)中的事物抽象成對(duì)象模型华匾,對(duì)象具有內(nèi)部狀態(tài)和特定行為映琳。

市面上的面向?qū)ο笳Z(yǔ)言中都有類(class)的概念,類內(nèi)部封裝了一些屬性(有些語(yǔ)言沒(méi)有屬性蜘拉,只有字段)和方法萨西。但是類究竟是什么呢?它其實(shí)就是一種數(shù)據(jù)類型旭旭,而一般我們所說(shuō)的接口(interface)谎脯,便相當(dāng)于抽象數(shù)據(jù)類型(Abstract Data Type, ADT)持寄。數(shù)據(jù)類型源梭、抽象數(shù)據(jù)類型和數(shù)據(jù)結(jié)構(gòu)聽(tīng)著有點(diǎn)像娱俺,但它們還是不一樣的:

  • 數(shù)據(jù)結(jié)構(gòu):用來(lái)反映一個(gè)數(shù)據(jù)的內(nèi)部構(gòu)成,即一個(gè)數(shù)據(jù)由哪些成分?jǐn)?shù)據(jù)構(gòu)成废麻,以什么方式構(gòu)成荠卷,呈什么結(jié)構(gòu)。邏輯上的數(shù)據(jù)結(jié)構(gòu)反映成分?jǐn)?shù)據(jù)之間的邏輯關(guān)系烛愧,物理上的數(shù)據(jù)結(jié)構(gòu)反映成分?jǐn)?shù)據(jù)在計(jì)算機(jī)內(nèi)的存儲(chǔ)安排油宜。數(shù)據(jù)結(jié)構(gòu)是數(shù)據(jù)存在的形式。
  • 數(shù)據(jù)類型:數(shù)據(jù)按照進(jìn)行數(shù)據(jù)結(jié)構(gòu)分類屑彻,具有相同數(shù)據(jù)結(jié)構(gòu)的數(shù)據(jù)屬同一類验庙。同一類數(shù)據(jù)的全體稱為數(shù)據(jù)類型。
  • 抽象數(shù)據(jù)類型:一個(gè)數(shù)學(xué)模型以及定義在此數(shù)學(xué)模型上的一組操作社牲。可理解為數(shù)據(jù)類型的進(jìn)一步抽象悴了。即把數(shù)據(jù)類型和數(shù)據(jù)類型上的運(yùn)算封裝在一起搏恤。

我們口中常說(shuō)的數(shù)據(jù)結(jié)構(gòu),其實(shí)大部分時(shí)候都是指抽象數(shù)據(jù)類型湃交,比如我們說(shuō)到棧(Stack)的時(shí)候熟空,是指一種具有pushpop操作,數(shù)據(jù)遵循先進(jìn)后出順序的ADT搞莺。所以我們當(dāng)然可以定義一個(gè)叫Stack的類息罗,去實(shí)現(xiàn)pushpop操作,無(wú)論具體實(shí)現(xiàn)細(xì)節(jié)是怎樣的才沧,它都可以稱為棧迈喉。而我們實(shí)例化一個(gè)對(duì)象的時(shí)候,便是申請(qǐng)了一塊內(nèi)存空間温圆,里面保存了:

  • 類中定義的一些基本數(shù)據(jù)類型(或者其他值類型)的拷貝
  • 指向函數(shù)(或稱方法)和其他對(duì)象的指針

上面兩點(diǎn)說(shuō)的都是類中定義的成員變量和成員方法挨摸,具體的實(shí)現(xiàn)不同的語(yǔ)言會(huì)有些差別。至于靜態(tài)變量和靜態(tài)方法跟對(duì)象并沒(méi)有關(guān)系岁歉,它們其實(shí)相當(dāng)于是全局的得运,類名只是起到了命名空間的作用。

說(shuō)了這么多锅移,順便也說(shuō)說(shuō)Swift中的類型吧熔掺,Swift中的classstruct非剃、enum置逻、closure都是數(shù)據(jù)類型,至于協(xié)議protocol就是抽象數(shù)據(jù)類型了努潘。一個(gè)protocol定義一組數(shù)據(jù)和操作诽偷,可以被class坤学、structenum實(shí)現(xiàn)报慕。至于集合類型深浮,Swift中原生的有三種——ArraySetDictionary眠冈,平常開(kāi)發(fā)基本已經(jīng)夠用了飞苇,但是如果我們想要實(shí)現(xiàn)諸如StackQueue這樣的數(shù)據(jù)結(jié)構(gòu)蜗顽,也是非常方便的:

//棧
struct Stack<T> {
    var items = [T]()
    
    //棧頂指針
    var top: Int {
        return items.count - 1
    }
    
    var isEmpty: Bool {
        return items.isEmpty
    }
    
    //加上mutating才能改變struct中的屬性
    //因?yàn)閟truct是值類型布卡,默認(rèn)是不可變的
    mutating func push(item: T) {
        items.append(item)
    }
    
    mutating func pop() -> T {
        return items.removeLast()
    }
}

//隊(duì)列
struct Queue<T> {
    var items = [T]()
    
    //入隊(duì)
    mutating func enqueue(item: T) {
        items.append(item)
    }
    
    mutating func dequeue(item: T) -> T {
        return items.removeFirst()
    }
}

這里我使用了范型,這樣StackQueue中的元素就可以為任意類型雇盖,而且保證了類型安全,譬如

var intStack = Stack<Int>()
intStack.push(1)
intStack.push(2)
let topElement = intStack.pop()    //topElement = 2

var stringQueue = Queue<String>()
stringQueue.enqueue("Swift")
stringQueue.enqueue("C#")
let str= stringQueue.dequeue()     //str = "Swift"

Swift不直接支持指針忿等,但是class是引用類型,對(duì)于實(shí)現(xiàn)鏈表崔挖、二叉樹(shù)這樣的基于指針的數(shù)據(jù)結(jié)構(gòu)來(lái)說(shuō)贸街,也夠用了。下面是鏈表的Swift實(shí)現(xiàn):

//節(jié)點(diǎn)(只能用class狸相,struct不支持類型嵌套薛匪,也就是Node<T>內(nèi)部不能聲明類型為Node<T>的屬性)
class Node<T: Equatable> {
    var value: T?
    var next: Node<T>!
    var prev: Node<T>!
    init(value: T?) {
        self.value = value
    }
}

//帶哨兵(nilNode)的鏈表,沒(méi)有head和tail
class LinkedList<T: Equatable> {
    
    var nilNode: Node<T>
    
    init() {
        nilNode = Node<T>(value: nil)
        nilNode.next = nilNode
        nilNode.prev = nilNode
    }
    
    //線性搜索
    func search(value: T) -> Node<T> {
        var node = nilNode.next
        //node.value為空則說(shuō)明node是nilNode脓鹃,因?yàn)槠渌?jié)點(diǎn)的value都由值
        while let v = node.value {
            if v != value {
                node = node.next
            } else {
                break
            }
        }
        return node
    }
    
    //插入到nilNode之后
    func insert(value: T) {
        let node = Node<T>(value: value)
        node.next = nilNode.next
        nilNode.next.prev = node
        nilNode.next = node
        node.prev = nilNode
    }
    
    func delete(value: T) {
        let node = search(value)
        assert(node.value != nil, "Value not found in LinkedList.")
        node.prev.next = node.next
        node.next.prev = node.prev
    }
}

二叉樹(shù)的三種遍歷方式:

class Tree<T: Equatable> {
    var value: T
    var leftChild: Tree<T>!
    var rightChild: Tree<T>!
    init(value: T) {
        self.value = value
    }
}

//樹(shù)中序遍歷
func inorderTreeWalk<T>(tree: Tree<T>?) {
    guard let node = tree else {
        return
    }
    
    inorderTreeWalk(node.leftChild)
    print(node.value)
    inorderTreeWalk(node.rightChild)
}

//前序
func preorderTreeWalk<T>(tree: Tree<T>?) {
    guard let node = tree else {
        return
    }
    
    print(node.value)
    preorderTreeWalk(node.leftChild)
    preorderTreeWalk(node.rightChild)
}
//后序
func postorderTreeWalk<T>(tree: Tree<T>?) {
    guard let node = tree else {
        return
    }
    
    postorderTreeWalk(node.leftChild)
    postorderTreeWalk(node.rightChild)
    print(node.value)
}

Int類型為鍵的哈希表

struct Element<T: Equatable>: Equatable {
    var key: Int?
    var value: T?
    init(key: Int?, value: T?) {
        self.key = key
        self.value = value
    }  
}
func ==<T>(lhs: Element<T>, rhs: Element<T>) -> Bool {
    return lhs.key == rhs.key && lhs.value == rhs.value
}

//哈希表
struct HashTable<T: Equatable> {
    typealias E = Element<T>
    
    var size: Int
    var memory : [LinkedList<E>?]
    init(size: Int) {
        self.size = size
        memory = [LinkedList<E>?](count: size, repeatedValue: nil)
    }
    
    //假定關(guān)鍵字都是Int
    func hash(key: Int) -> Int {
        return key % size
    }
    
    subscript(key: Int) -> T? {
        get {
            guard let linkedList = memory[hash(key)] else {
                return nil
            }
            let element = Element<T>(key: key, value: nil)
            return linkedList.search(element).value?.value
        }
        set {
            let element = Element<T>(key: key, value: newValue)
            let linkedList = memory[hash(key)] ?? LinkedList<E>()
            linkedList.insert(element)
            memory[hash(key)] = linkedList
        }
        
    }
    
//    mutating func insert(key: Int, value: T) {
//        memory[hash(key)] = value
//    }
}

這段哈希表代碼有一些需要說(shuō)明的地方:

  • 對(duì)于存入哈希表中的元素逸尖,我定義了一個(gè)Element類型,它實(shí)現(xiàn)了Equatable協(xié)議瘸右,表明是可判等的娇跟,然后再重載==操作符,就可以用==符號(hào)來(lái)對(duì)兩個(gè)Element類型的實(shí)例進(jìn)行比較了尊浓。同時(shí)也使用了范型逞频,范型類型也必須是實(shí)現(xiàn)了Equatable協(xié)議的類型,譬如Element<Int>栋齿、Element<String>都可以苗胀。
  • 在哈希表中我使用了一個(gè)最簡(jiǎn)單的哈希函數(shù),就是一個(gè)取模操作瓦堵。對(duì)于碰撞沖突(不同的key值經(jīng)過(guò)hash函數(shù)處理后返回了相同的地址)的處理我使用了鏈接法基协,也就是說(shuō)哈希表的每個(gè)槽都保存了一個(gè)鏈表,多個(gè)值被哈希到同一個(gè)地址的話就都保存在鏈表中菇用。碰撞處理還可以使用開(kāi)放尋址法澜驮,就是一旦哈希到相同的地址就用不同的哈希函數(shù)再進(jìn)行哈希,直到找到一個(gè)空的地址惋鸥,不過(guò)在實(shí)踐中使用得較少杂穷,一般還是使用鏈接法悍缠。
  • 自定義下標(biāo),可以通過(guò)下標(biāo)直接操作哈希表:
var hashTable = HashTable<Int>(size: 10)
hashTable[1] = 20
let value1 = hashTable[1]       //value1 = 20
let value2 = hashTable[33]      //value2 = nil

上次我寫(xiě)快排的時(shí)候提到過(guò)耐量,除了快排之外飞蚓,還有兩種算法的時(shí)間復(fù)雜度也是O(nlgn),就是歸并排序和堆排序廊蜒。雖然在實(shí)踐中趴拧,快排和歸并排序的效果更好些,大部分語(yǔ)言的標(biāo)準(zhǔn)庫(kù)中提供的sort函數(shù)也是使用這兩種算法或其中一種山叮。但是堆排序中構(gòu)建的堆卻是一種非常實(shí)用的數(shù)據(jù)結(jié)構(gòu)著榴,這個(gè)堆不是垃圾回收機(jī)制(GC)中的堆,而是一種完全二叉樹(shù)屁倔。它不僅可以用在堆排中脑又,還可以用來(lái)構(gòu)造一種有效的優(yōu)先隊(duì)列。先看看堆排吧汰现,我同樣用Swift實(shí)現(xiàn)了一下:

//二叉堆基本操作
func parent(index: Int) -> Int {
    return (index - 1) / 2
}

func leftChild(index: Int) -> Int {
    return 2 * index + 1
}

func rightChild(index: Int) -> Int {
    return 2 * index + 2
}

var heapSize = 0

//維護(hù)最大堆性質(zhì)
func maxHeapity(inout maxHeap: [Int], index: Int) {
    let left = leftChild(index)
    let right = rightChild(index)

    //在index挂谍,left,right三者中取最大值
    var largest = (left < heapSize && maxHeap[left] > maxHeap[index]) ? left : index
    largest = (right < heapSize && maxHeap[right] > maxHeap[largest]) ? right : largest
    
    if largest != index {
        (maxHeap[index], maxHeap[largest]) = (maxHeap[largest], maxHeap[index])
        maxHeapity(&maxHeap, index: largest)
    }
}

//建堆
func buildMaxHeap(inout list: [Int]) {
    heapSize = list.count
    var index = list.count/2 - 1
    //index+1...endIndex都是葉子節(jié)點(diǎn)
    while index >= 0 {
        maxHeapity(&list, index: index--)
    }
}

//堆排序
func heapSort(inout list: [Int]) {
    buildMaxHeap(&list)
    
    var endIndex = heapSize - 1
    while endIndex > 0 {
        //將最大元素?fù)Q到底部
        (list[0], list[endIndex--]) = (list[endIndex], list[0])
        //將底部元素從堆中移除
        heapSize--
        //重新維持最大堆性質(zhì)
        maxHeapity(&list, index: 0)
    }
}

//test
var testList = [27, 999, 77, 5, 90, 63, 11, 8]
heapSort(&testList)

這里我構(gòu)建了一個(gè)最大堆瞎饲,最大堆的性質(zhì)就一條:maxHeap[parent(i)] >= maxHeap[i],也就是說(shuō)父節(jié)點(diǎn)不小于孩子節(jié)點(diǎn)炼绘;同理嗅战,最小堆的性質(zhì)是minHeap[parent(i)] <= minHeap[i]

優(yōu)先隊(duì)列是一種用來(lái)維護(hù)一組含關(guān)鍵字(用key表示)的元素的數(shù)據(jù)結(jié)構(gòu)俺亮。一個(gè)最大優(yōu)先隊(duì)列支持以下操作:

  • insert(element):插入一個(gè)元素element
  • maximum:返回具有最大關(guān)鍵字的元素
  • extract-max:去掉并返回最大關(guān)鍵的元素
  • increase-key(element, k):將元素element的關(guān)鍵字增加到k驮捍,k >= element.key

最大優(yōu)先隊(duì)列的應(yīng)用很多,譬如系統(tǒng)的作業(yè)調(diào)度脚曾,最大優(yōu)先隊(duì)列記錄并維護(hù)將要執(zhí)行的各個(gè)任務(wù)以及它們之間的相對(duì)優(yōu)先級(jí)东且,當(dāng)一個(gè)任務(wù)完成或中斷后,調(diào)度器調(diào)用extract-max從所有的等待任務(wù)中選出具有最高優(yōu)先級(jí)的任務(wù)執(zhí)行本讥。在任何時(shí)候珊泳,調(diào)度器都可以調(diào)用insert把一個(gè)新任務(wù)加入隊(duì)列。

最小優(yōu)先隊(duì)列支持的操作包括insert拷沸、minimum色查、extract-min和decrease-key。最小優(yōu)先隊(duì)列可以被用于基于事件驅(qū)動(dòng)的模擬器撞芍。隊(duì)列中保存事件秧了,每個(gè)事件都有一個(gè)發(fā)生時(shí)間作為其關(guān)鍵字key。事件按照時(shí)間順序進(jìn)行序无,每次調(diào)用extract-min返回隊(duì)列中具有最小時(shí)間的事件验毡。新事件產(chǎn)生時(shí)衡创,模擬器調(diào)用insert進(jìn)行插入。

顯然優(yōu)先隊(duì)列可以用堆輕易實(shí)現(xiàn)晶通,而且十分高效璃氢。我就不給出代碼了,好困好想睡覺(jué)录择。拔莱。。

IT界每天都有新技術(shù)出現(xiàn)隘竭,但其實(shí)很多東西都換湯不換藥塘秦,都是在炒冷飯,我們不應(yīng)該被種種表象迷惑而疲于奔命动看。打好基礎(chǔ)尊剔,慢慢地就會(huì)摸到整個(gè)體系的脈絡(luò),去蕪存菁菱皆,才能在這不進(jìn)則退的信息化浪潮中安然立世须误。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市仇轻,隨后出現(xiàn)的幾起案子京痢,更是在濱河造成了極大的恐慌,老刑警劉巖篷店,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件祭椰,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡疲陕,警方通過(guò)查閱死者的電腦和手機(jī)方淤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)蹄殃,“玉大人携茂,你說(shuō)我怎么就攤上這事∽缪遥” “怎么了讳苦?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)按厘。 經(jīng)常有香客問(wèn)我医吊,道長(zhǎng),這世上最難降的妖魔是什么逮京? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任卿堂,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘草描。我一直安慰自己览绿,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開(kāi)白布穗慕。 她就那樣靜靜地躺著饿敲,像睡著了一般。 火紅的嫁衣襯著肌膚如雪逛绵。 梳的紋絲不亂的頭發(fā)上怀各,一...
    開(kāi)封第一講書(shū)人閱讀 51,287評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音术浪,去河邊找鬼瓢对。 笑死,一個(gè)胖子當(dāng)著我的面吹牛胰苏,可吹牛的內(nèi)容都是我干的硕蛹。 我是一名探鬼主播,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼硕并,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼法焰!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起倔毙,我...
    開(kāi)封第一講書(shū)人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤埃仪,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后陕赃,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體贵试,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年凯正,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片豌蟋。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡廊散,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出梧疲,到底是詐尸還是另有隱情允睹,我是刑警寧澤,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布幌氮,位于F島的核電站缭受,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏该互。R本人自食惡果不足惜米者,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蔓搞,春花似錦胰丁、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至蒲祈,卻和暖如春甘萧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背梆掸。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工扬卷, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人沥潭。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓邀泉,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親钝鸽。 傳聞我的和親對(duì)象是個(gè)殘疾皇子汇恤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354

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

  • 本文涉及更多的是概念,代碼部分請(qǐng)參考之前寫(xiě)過(guò)的 2 篇博客 基于Javascript的排序算法基本數(shù)據(jù)結(jié)構(gòu)和查找算...
    faremax閱讀 1,240評(píng)論 0 2
  • 1 序 2016年6月25日夜拔恰,帝都因谎,天下著大雨,拖著行李箱和同學(xué)在校門口照了最后一張合照颜懊,搬離寢室打車去了提前租...
    RichardJieChen閱讀 5,098評(píng)論 0 12
  • 科大的落葉真的很美财岔,落在地上一層一層的折疊起來(lái),金黃金黃的河爹,給科大校園增加了無(wú)限風(fēng)光匠璧。因?yàn)橹跋逻^(guò)雨,在沒(méi)有硬化的...
    健坤媛閱讀 181評(píng)論 0 0
  • 今天奶奶把我送到家我立刻把書(shū)包里東西趕緊拿出來(lái)咸这。我一個(gè)個(gè)慢慢寫(xiě)覺(jué)得特別好看夷恍。我給奶奶看。奶奶夸我好寶寶奶奶獎(jiǎng)勵(lì)我看...
    孔雯茜閱讀 202評(píng)論 0 0
  • iOS提供了很多的字體樣式媳维。有時(shí)候我們?cè)陂_(kāi)發(fā)應(yīng)用的時(shí)候可能用到不同的字體酿雪,通過(guò)此Demo我們可以獲取到所有的字體樣...
    嘖嘖嘖_野獸閱讀 3,468評(píng)論 0 2