COMP9021 Principles of Programming WEEK8

1. Linked List

链表是基础的数据结构,与之对应的另外一个选择是数组。在查询方面,数组有优势,复杂度是O(1),但是在插入删除等操作上不如链表,复杂度是O(n);链表在插入删除等操作上有优势,复杂度是O(1),而查询上不如数组,必须按照顺序检索,复杂度是O(n)。
以上特征的原因来自于二者不同的储存方式,数组是在内存空间中选取连续单元,所以查询速度极快,但是如果插入元素超过了附近可用的内存空间,则要整体复制迁移,重新分配内存空间。相比之下,链表的存储不是连续的内存空间,每一个位置上记录与之相邻的元素,如果是单链表,只记录下一个元素的内存位置,双链表的话还会记录上一个元素位置。

1.1 Linked List基本构成

一般要有两个class,一个定义单个Node的构成(value和element address),另一个定义整体的list(head起始位置)

class Node:
    def __init__(self, value):
        self.value = value
        self.next_node = None
#单链表的Node有两个部分构成,一个是当前element的value,另一个是下一个element的address

class LinkedList:
    def __init__(self):
        self.head = None
#Linked list的必须元素只有head

1.2 Linked List的生成和显示

Linked List一般需要根据Class Node生成一个连续的链表,并且可以根据需要显示链表的元素。

class Node:
    def __init__(self, value):
        self.value = value
        self.next_node = None

class LinkedList:
    def __init__(self, L = None):
        if not L:
        #课上的代码比较冗余,这里做了update,原代码是"if L is None or len(L) == 0",两个判断可以合并,因为None和[]的boolean判断都是False
            self.head = None
        self.head = Node(L[0])
        current_node = self.head
        #将head赋给L中的第一个element,当下的node也是第一个element
        for e in L[1: ]:
            current_node.next_node = Node(e)
            current_node = current_node.next_node

    def print_list(self, sep = ', '):
        values = []
        node = self.head
        #从head开始,只要node有值,全都变成str加入values中,方便格式化输出
        while node:
            values.append(str(node.value))
            node = node.next_node
        print(sep.join(values))

1.3 Linked List插入元素

常见的插入操作是在两端加入,所以定义两个function实现头尾两端插入元素的功能。

#Node和LinkedList上文定义过的属性功能不再重复,这里只附两个函数的代码
class LinkedList:
    def append(self, value):
    #在最后插入新的node
        new_node = Node(value) 
        if not self.head:
            self.head = new_node
        #如果当前Linked List中没有node,则让head指向这个新的Node
        else:
            current_node = self.head
            while current_node.next_node:
                current_node = current_node.next_node
            current_node.next_node = new_node
        #如果当下有node,则遍历所有node,直到找到最后一个node,由于while的body将当前node指向了下一个,所以终止条件是判断下一个node是否为真

    def prepend(self, value):
        new_node = Node(value)
        if not self.head:
            self.head = new_node
        else:
            new_node.next_node = self.head
            #新的node指向head,这里的head是一个linked list
            self.head = new_node
            #head指向new node,这里的head是上文提到过的LinkedList class中的一个属性

1.4 Linked List删除元素

同样,常见的删除位置是在首尾两端,和插入的方法类似,只是删除时的条件判断更加复杂。

class LinkedList:
    def delete_first_element(self):
        if not self.head:
            return 
        if not self.head.next_node:
        #之所以要比insert多加一个判断,是因为如果只有一个元素,head要指向None,如果多于一个元素,head指向剩下紧邻的元素
            self.head = None
        else:
            self.head = self.head.next_node
        #链表中删除元素,其实不用真的将值改变,或者移动后续元素,只需要在链表的关联中删除该元素的地址,任何元素都将无法找到这个元素,也就被删除了。

    def delete_last_element(self):
        if not self.head:
            return 
        if not self.head.next_node:
        #之所以要比insert多加一个判断,是因为如果只有一个元素,head要指向None,如果多于一个元素,head指向剩下紧邻的元素
            self.head = None
        else:
            current_node = self.head
            while current_node.next_node.next_node:
                current_node = current_node.next_node
            current_node.next_node = None
            #和在最后插入位置类似,循环判断条件需要注意,因为要删除最后一个元素,我们要让当前位置停留在倒数第二个元素,而while的body内会更改当前元素到下一个,所以判别结束条件应该是当下元素后面的第三个元素为空。

1.4 Linked List排序判断

Linked List的数据结构最擅长排序,所以自然要在class的定义中判断排序状态。

class LinkedList:
    def __init__(self, L = None, comparison_key = lambda x: x):
        if L is None or not len(L):
            self.head = None
        else:
            self.head = Node(L[0])
            current_last_node = self.head
            for e in L[1: ]:
                current_last_node.next_node = Node(e)
                current_last_node = current_last_node.next_node
        self.comparison_key = comparison_key

    def is_sorted(self):
        if not self.head or not self.head.next_node:
            return True
        #如果链表为空,或者只有一个元素,都认为是有序的
        node = self.head
        while node.next_node:
            if self.comparison_key(node.value) > self.comparison_key(node.next_node.value):
                return False
            node = node.next_node
        return True

1.5 Linked List逆序

和上文同样的原因,逆序也是常用功能。

class LinkedList:
    def reverse(self):
        if not self.head or not self.head.next_node:
            return True
        tail = self.head
        #最后的位置是现在的head处
        current_node = self.head.next_node
        #要处理的元素是head后面一个
        tail.next_code = None
        #切断tail和其他元素的联系
        while current_node:
            next_node = current_node.next_node
            #找到下一个要逆序的元素
            current_node.next_node = tail
            #建立当下处理元素的逆序关系
            tail = current_node
            #标记当前逆序list中最后一个元素
            current_node = next_node
            #处理好当前的元素后,准备再次循环处理下面的元素
        self.head = tail
        #全部逆序后,head应该指向tail的标记处      

2. Deque实现

Deque的数据结构也是Linked List,可以方便的插入、删除数据,一般都是在头尾操作元素。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,519评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,842评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,544评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,742评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,646评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,027评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,513评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,169评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,324评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,268评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,299评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,996评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,591评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,667评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,911评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,288评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,871评论 2 341

推荐阅读更多精彩内容