CS 基礎(chǔ):線性表

線性表

零個(gè)或多個(gè)數(shù)據(jù)元素的有限序列鸭蛙。

線性表的結(jié)構(gòu)

  • 順序存儲(chǔ)
  • 鏈?zhǔn)酱鎯?chǔ)

順序存儲(chǔ)結(jié)構(gòu)

用一段地址連續(xù)的存儲(chǔ)單元依次存儲(chǔ)線性表的元素姨伤,因?yàn)榈刂肥沁B續(xù)的熙暴,順序存儲(chǔ)結(jié)構(gòu)元素讀取很快肌幽,但是這個(gè)結(jié)構(gòu)的線表進(jìn)行插入以及刪除等操作涉及到的元素的地址都要進(jìn)行變換贪庙,都很不方便,于是衍生出下面那個(gè)鏈?zhǔn)降慕Y(jié)構(gòu)团赁。
一個(gè)圖:



34567的存儲(chǔ)位置都要變更育拨。

鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)(鏈表)

鏈表的兩種結(jié)構(gòu)

  • 單向鏈表:每一個(gè)節(jié)點(diǎn)的只有下一個(gè)節(jié)點(diǎn)的引用
  • 雙向鏈表:每一個(gè)節(jié)點(diǎn)有前一個(gè)和后一個(gè)節(jié)點(diǎn)的引用

每一個(gè)鏈表都有頭節(jié)點(diǎn)以及尾節(jié)點(diǎn):

實(shí)現(xiàn)一個(gè)雙向鏈表

推薦研讀Swift Algorithm Club: Swift Linked List Data Structure

構(gòu)造一個(gè)節(jié)點(diǎn)類

public class Node{
    var value : String
    init(value:String){
        self.value = value
    }
}

value 可以是任意的數(shù)據(jù)類型,根據(jù)鏈表的用途來(lái)定然痊。在最后一個(gè)章節(jié)用泛型來(lái)改造這個(gè)數(shù)據(jù)結(jié)構(gòu)。

加入對(duì)下一個(gè)節(jié)點(diǎn)的引用

public class Node{
    var next : Node?
    var value : String
    init(value:String){
        self.value = value
    }
}

加入對(duì)上一個(gè)節(jié)點(diǎn)的引用

public class Node{
    var next : Node?
    weak var previous : Node?
    var value : String
    init(value:String){
        self.value = value
    }
}

建立一個(gè)鏈表類

public class List {
    fileprivate var head : Node?
    private var tail : Node?
    
    public var isEmpty : Bool{
        return head == nil
    }
    
    public var head : Node?{
        return head
    }
    
    public var tail : Node?{
        return tail
    }
}

讓鏈表類可以添加節(jié)點(diǎn)元素

public class List {
    fileprivate var head : Node?
    private var tail : Node?
    
    public var isEmpty : Bool{
        return head == nil
    }
    
    public var head : Node?{
        return head
    }
    
    public var tail : Node?{
        return tail
    }
    
    public func append(value:String){
        let newNode = Node(value:value)
        
        if let tailNode = tail{
            newNode.previous = tailNode
            tailNode.next = newNode
        }else{
            head = newNode
        }
        
        tail = newNode
    }
}

List 類的實(shí)踐

首先添加一個(gè) List 的 extension 協(xié)助打印輸出

extension List{
    public var description : String{
        var text = "["
        var node = head
        
        while node != nil{
            text += "\(node!.value)"
            node = node!.next
            if node != nil {
                text += " , "
            }
        }
        return text + "]"   
    }
}
let listt = List()
listt.append(value:"熊大")
listt.append(value:"熊二")
listt.append(value:"周末")
listt.append(value:"蛋蛋")

print(listt.description)

打印結(jié)果:

[熊大 , 熊二 , 周末 , 蛋蛋]

根據(jù)下標(biāo)讀取鏈表節(jié)點(diǎn)

由于鏈表的性質(zhì)屉符,從頭結(jié)點(diǎn)開始讀取剧浸,直到讀到對(duì)應(yīng)的下標(biāo)停止并返回相應(yīng)的節(jié)點(diǎn)锹引。
給 List 類添加一個(gè)讀取下標(biāo)對(duì)應(yīng)節(jié)點(diǎn)函數(shù):

public func nodeAt(index:Int) -> Node? {
        if index >= 0 {
            var node = head
            var i = index
            
            while node != nil {
                if i == 0 {
                    return node
                }
                i -= 1
                node = node!.next
            }
        }
        return nil
    }

清空鏈表

只要將首節(jié)點(diǎn)與尾節(jié)點(diǎn)置為 nil 整個(gè)鏈表就會(huì)被置空。
給 List 添加函數(shù):

public func removeAll() {
        head = nil
        tail = nil
    }

移除其中某個(gè)節(jié)點(diǎn)

移除節(jié)點(diǎn)的三種情況:

  • 移除首節(jié)點(diǎn):如圖變更 Head 指針以及 Node1 的 previous 指針
  • 移除尾節(jié)點(diǎn):如圖變更 Tail 指針以及 Node2 的 next 指針指為 nil唆香。
  • 移除非首尾節(jié)點(diǎn):如圖只需要變更被移除的 Node1 節(jié)點(diǎn)的上一個(gè)節(jié)點(diǎn) Node0 的 next 指針指向 Node2嫌变,Node2 的 previous 指針指向 Node0,那么 Node1 節(jié)點(diǎn)就已經(jīng)脫離了鏈表躬它。
Screen Shot 2017-02-07 at 10.41.06 AM.png

給 List 添加移除節(jié)點(diǎn)函數(shù):

public func remove(node: Node){
        let prev = node.previous
        let next = node.next
        
        if let prev = prev {
            prev.next = next
        }else {
            head = next
        }
        
        next?.previous = prev
        
        if next == nil {
            tail = prev
        }
        
        node.previous = nil
        node.next = nil
    }

在進(jìn)行一次實(shí)踐

代碼:

let list = List()
list.append(value:"熊大")
list.append(value:"熊二")
list.append(value:"周末")
list.append(value:"蛋蛋")
print(list.description)

let node = list.nodeAt(index:1)
list.remove(node:node!)
print(list.description)

list.removeAll()
print(list.description)

輸出:

[熊大 , 熊二 , 周末 , 蛋蛋]
[熊大 , 周末 , 蛋蛋]
[]

使用泛型來(lái)改造這個(gè)鏈表類

改造節(jié)點(diǎn) Node 類

public class Node<T>{
    var next : Node<T>?
    weak var previous : Node<T>?
    var value : T
    init(value:T){
        self.value = value
    }
}

改造鏈表 List 類

public class List<T> {
    fileprivate var head : Node<T>?
    private var tail : Node<T>?
    
    public var isEmpty : Bool{
        return head == nil
    }
    
    public var first : Node<T>?{
        return head
    }
    
    public var last : Node<T>?{
        return tail
    }
    
    public func append(value:T){
        let newNode = Node(value:value)
        
        if let tailNode = tail{
            newNode.previous = tailNode
            tailNode.next = newNode
        }else{
            head = newNode
        }
        
        tail = newNode
    }
    
    public func nodeAt(index:Int) -> Node<T>? {
        if index >= 0 {
            var node = head
            var i = index
            
            while node != nil {
                if i == 0 {
                    return node
                }
                i -= 1
                node = node!.next
            }
        }
        return nil
    }
    
    public func removeAll() {
        head = nil
        tail = nil
    }
    
    public func remove(node: Node<T>){
        let prev = node.previous
        let next = node.next
        
        if let prev = prev {
            prev.next = next
        }else {
            head = next
        }
        
        next?.previous = prev
        
        if next == nil {
            tail = prev
        }
        
        node.previous = nil
        node.next = nil
    }
}

實(shí)踐

利用泛型特性改造之后腾啥,這個(gè)鏈表類則可以儲(chǔ)存任意類型的值,比較靈活冯吓。

輸入:

let list = List<String>()
list.append(value:"熊大")
list.append(value:"熊二")
list.append(value:"周末")
list.append(value:"蛋蛋")

輸出:

[熊大 , 熊二 , 周末 , 蛋蛋]

end

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末倘待,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子组贺,更是在濱河造成了極大的恐慌凸舵,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件失尖,死亡現(xiàn)場(chǎng)離奇詭異啊奄,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)掀潮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門菇夸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人仪吧,你說(shuō)我怎么就攤上這事庄新。” “怎么了邑商?”我有些...
    開封第一講書人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵摄咆,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我人断,道長(zhǎng)吭从,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任恶迈,我火速辦了婚禮涩金,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘暇仲。我一直安慰自己步做,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開白布奈附。 她就那樣靜靜地躺著全度,像睡著了一般。 火紅的嫁衣襯著肌膚如雪斥滤。 梳的紋絲不亂的頭發(fā)上将鸵,一...
    開封第一講書人閱讀 51,708評(píng)論 1 305
  • 那天勉盅,我揣著相機(jī)與錄音,去河邊找鬼顶掉。 笑死草娜,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的痒筒。 我是一名探鬼主播宰闰,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼簿透!你這毒婦竟也來(lái)了移袍?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤萎战,失蹤者是張志新(化名)和其女友劉穎咐容,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蚂维,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡戳粒,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了虫啥。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蔚约。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖涂籽,靈堂內(nèi)的尸體忽然破棺而出苹祟,到底是詐尸還是另有隱情,我是刑警寧澤评雌,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布树枫,位于F島的核電站,受9級(jí)特大地震影響景东,放射性物質(zhì)發(fā)生泄漏砂轻。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一斤吐、第九天 我趴在偏房一處隱蔽的房頂上張望搔涝。 院中可真熱鬧,春花似錦和措、人聲如沸庄呈。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)诬留。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間文兑,已是汗流浹背傀广。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留彩届,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓誓酒,卻偏偏與公主長(zhǎng)得像樟蠕,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子靠柑,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355

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

  • 1.線性表的定義 線性表:零個(gè)或多個(gè)數(shù)據(jù)元素的有限序列序列:也就是說(shuō)元素之間是有順序的,若元素存在多個(gè),則第一個(gè)元...
    e40c669177be閱讀 2,064評(píng)論 6 15
  • 原創(chuàng)文章&經(jīng)驗(yàn)總結(jié)&從校招到A廠一路陽(yáng)光一路滄桑 詳情請(qǐng)戳www.codercc.com 1.Concurrent...
    你聽___閱讀 6,544評(píng)論 0 5
  • 一.線性表 定義:零個(gè)或者多個(gè)元素的有限序列寨辩。也就是說(shuō)它得滿足以下幾個(gè)條件:??①該序列的數(shù)據(jù)元素是有限的。??②...
    Geeks_Liu閱讀 2,701評(píng)論 1 12
  • 從數(shù)據(jù)的邏輯結(jié)構(gòu)來(lái)分歼冰,數(shù)據(jù)元素之間存在的關(guān)聯(lián)關(guān)系被稱為數(shù)據(jù)的邏輯結(jié)構(gòu)靡狞。歸納起來(lái),應(yīng)用程序中的數(shù)據(jù)大致喲如下四種基本...
    Jack921閱讀 929評(píng)論 0 2
  • 黃昏時(shí)分隔嫡,北京五環(huán)外的一處建筑工地旁甸怕,55歲的老范坐在馬路牙子上吃著他的晚飯。三個(gè)饅頭腮恩、一袋混合著豆腐干梢杭、花生米和...
    8b1571ffc0d7閱讀 289評(píng)論 0 1