学习笔记-单链表(Python)

顺序表可以在O(1)的时间内定位元素,但是插入或者删除需要O(n)的时间,因为其需要移动大量的元素块。

链表的实现不需要连续的存储区。链表的每个结点含有表元素和指向后继元素的指针。

在链表表首插入和删除元素的复杂度都是O(1),在其他位置插入和删除元素的复杂度都是O(n)。


下面定义一个链表的结点类:

class LNode:
    def __init__(self, elem, pnext = None):
        self.elem = elem
        self.pnext = pnext


1、向链表插入元素

表首插入:在表首插入元素,需要将新结点的pnext指向原来的表首元素,然后修改表头变量,使其指向新的结点


示例代码:

q = LNode(13)
q.pnext = head.pnext
head = q

一般情况插入:要想在链表的某个位置插入元素,需要找到插入位置的前一个结点pre,将新结点的pnext指向原来pre结点的后一个结点,并且将pre结点的pnext指向新的结点。


q = LNode(13)
q.pnext = pre.pnext
pre.pnext = q

尾端插入:需要先找到最后一个结点,然后在其后面插入新的结点。

def append(self, elem):
    if self.head is None:
        self.head = LNode(elem)
        return
    p = self.head
    while p.pnext is not None:
        p = p.pnext
    p.pnext = LNode(elem)


2、删除链表中的元素

删除表首元素:删除表首元素只需要将表头指针指向表中的第二个结点即可。被丢弃的结点会被Python解释器自动回收。

head = head.pnext

一般情况的删除:一般情况删除需要先找到被删元素的前一个结点pre,将其pnext指向被删结点的下一个结点即可。

pre.pnext = pre.pnext.pnext


删除表尾元素:需要找到倒数第二个结点,也就是p.pnext.pnext为None的p。

def pop_last(self):
    if self.head is None:
        return False
    p = self.head
    if p.pnext is None:
        e = p.elem
        self.head = None
        return e
    while p.pnext.pnext is not None:
        p = p.pnext
    e = p.pnext.elem
    p.pnext = None
    return e
打印链表中所有元素:
def printall(self):
    p = self.head
    while p is not None:
        print(p.elem, end='')
        if p.pnext is not None:
            print(', ', end='')
        p = p.pnext
    print('')

以下是所有的代码:

class LinkedListUnderflow(ValueError):
    pass

class LNode:
    def __init__(self, elem, pnext=None):
        self.elem = elem
        self.pnext = pnext

class LList:
    def __init__(self):
        self.head = None
        self.length = 0 #对结点进行计数

    def is_empty(self):
        return self.head is None

    def prepend(self, elem): #在表首添加元素
        self.head = LNode(elem, self.head)
        self.length += 1

    def append(self, elem):#在表尾添加元素
        if self.head is None: #如果表头为空,说明是空表,直接将元素添加到表头
            self.head = LNode(elem)
            self.length += 1
            return

        p = self.head
        while p.pnext is not None:
            p = p.pnext
        p.pnext = LNode(elem)
        self.length += 1

    def insert(self, index, value): #在一般位置插入元素
        if index > self.length:
            raise LinkedListUnderflow('in insert')
        else:
            p = self.head
            if index == 0: #如果在表首插入元素
                self.prepend(value)
                return

            i = 0
            while i < index-1: #找出插入结点的前一个结点
                p = p.pnext
                i += 1
            insert_node = LNode(value)
            insert_node.pnext = p.pnext #插入结点的pnext指向后一个结点
            p.pnext = insert_node #p的pnext指向插入结点
            self.length += 1
            return

    def delete(self, index):
        if index > self.length:
            raise LinkedListUnderflow('in insert')
        else:
            if index == 0:
                self.head = self.head.pnext
                self.length -= 1
                return
            else:
                p = self.head
                i = 0
                while i < index-1:
                    p = p.pnext
                    i += 1
                p.pnext = p.pnext.pnext
                self.length -= 1
                return

    def pop_first(self):
        if self.head is None:
            raise LinkedListUnderflow('in pop')
        e = self.head.elem
        self.head = self.head.pnext
        return e

    def pop_last(self):
        if self.head is None:
            return False
        p = self.head
        if p.pnext is None:
            e = p.elem
            self.head = None
            return e
        while p.pnext.pnext is not None:
            p = p.pnext
        e = p.pnext.elem
        p.pnext = None
        return e

    def printall(self):
        p = self.head
        while p is not None:
            print(p.elem, end='')
            if p.pnext is not None:
                print(', ', end='')
            p = p.pnext
        print('')

    def clear(self):
        self.head = None #直接将表头指针置为None,就可以删除整个链表
        self.length = 0
        print('clear successfully')


if __name__=="__main__":
    lst = LList()
    for i in range(6):
        lst.append(i)
    lst.printall()
    lst.delete(3)
    lst.clear()
    lst.printall()
    print(lst.length)






猜你喜欢

转载自blog.csdn.net/qq_34840129/article/details/80762050