数据结构---单向链表(Python)

最近刷LeetCode,涉及到了很多链表的内容,都暂时跳过了。学习了一下传播智客的Python版数据结构,做一些笔记吧。

单项链表

单项链表也叫单链表,是链表中最简单的一种形式,它的每一个节点包含两个域,一个称为信息域(元素域),另一个称为链接域(指针域)。其中链接指向链表中的下一个节点,而最后一个节点的链接域则指向一个空值。

单链表节点单元如下图所示:

表元素域elem用来存放具体的数据,链接域next用来存放下一个节点的位置。

单链表的结构如下图所示:

变量p指向链表的头结点(首节点)的位置,从p出发能找到表中的任意节点。

节点的实现

class Node(object):
    def __init__(self,item):
        self.item = item
        self.next = None

单链表的常规操作

  • is_empty() 链表是否为空
  • length() 链表长度
  • travel() 遍历整个链表
  • add(item) 链表头部添加元素
  • append(item) 链表尾部添加元素
  • insert(pos, item) 指定位置添加元素
  • remove(item) 删除节点
  • search(item) 查找节点是否存在

单链表的实现

  • is_empty() 链表是否为空:

如果头结点为None,则链表为空

    def is_empty(self):

        return self._head == None
  • length() 链表长度

定义一个游标,游标的初始值指向头结点,定义一个累计节点数的变量,如果游标不指向尾结点None时,节点数累加,否则停止。

    def length(self):
        count = 0
        curr = self._head
        while curr != None:
            count += 1
            curr = curr.next

        return count
  • travel() 遍历整个链表
    def travel(self):
        curr = self._head
        while curr != None:
            print(curr.item)
            curr = curr.next
        print('')
  • append(item) 链表尾部添加元素
    def append(self,item):
        #通过节点类将传入的item值封装成节点单元
        node = Node(item)
        #先判断链表一开始是不是为空,如果为空,头结点直接指向node节点,否则遍历节点,找到尾结点再添加node
        if self.is_empty():
            self._head = node
        else:
            curr = self._head
            while curr.next != None:
                curr = curr.next
            curr.next = node
  • add(item) 链表头部添加元素

头部添加元素示意图:

    def add(self,item):
        node = Node(item)
        node.next == self._head
        self._head = node
  • insert(pos, item) 指定位置添加元素

指定位置添加元素示意图:

    def insert(self,pos,item):
        node = Node(item)
        #先判断一下插入位置的特殊情况,头部或是尾部,可以利用之前写好的函数;否则找到pos位置插入
        if pos <= 0:
            self.add(item)
        elif pos > self.length()-1:
            self.append(item)
        else:
            node = Node(item)
            curr = self._head
            count = 0
            while count != pos-1:
                curr = curr.next
                count += 1
            node.next = curr.next
            curr.next = node
  • remove(item) 删除节点

删除节点示意图:

    def remove(self,item):
        #两个游标,pre一直为curr的前一个节点
        curr = self._head
        pre = None
        while curr != None:
            if curr.item == item:
                if not pre:
                    self._head = curr.next
                else:
                    pre.next = curr.next
                break
            else:
                #往后移动
                pre = curr
                curr = curr.next
  • search(item) 查找节点是否存在
    def search(self, item):
        curr = self._head
        while curr != None:
            if curr.item == item:
                return True
            curr = curr.next

        return False

全部代码:

class Node(object):
    def __init__(self,item):
        self.item = item
        self.next = None

class SingleLink(object):
    def __init__(self):
        self._head = None

    def is_empty(self):

        return self._head == None

    def length(self):
        count = 0
        curr = self._head
        while curr != None:
            count += 1
            curr = curr.next

        return count

    def travel(self):
        curr = self._head
        while curr != None:
            print(curr.item)
            curr = curr.next
        print('')

    def append(self,item):
        node = Node(item)
        if self.is_empty():
            self._head = node
        else:
            curr = self._head
            while curr.next != None:
                curr = curr.next
            curr.next = node

    def add(self,item):
        node = Node(item)
        node.next == self._head
        self._head = node

    def insert(self,pos,item):
        node = Node(item)
        if pos <= 0:
            self.add(item)
        elif pos > self.length()-1:
            self.append(item)
        else:
            node = Node(item)
            curr = self._head
            count = 0
            while count != pos-1:
                curr = curr.next
                count += 1
            node.next = curr.next
            curr.next = node


    def remove(self,item):
        #两个游标,pre为curr的前一个节点
        curr = self._head
        pre = None
        while curr != None:
            if curr.item == item:
                if not pre:
                    self._head = curr.next
                else:
                    pre.next = curr.next
                break
            else:
                #往后移动
                pre = curr
                curr = curr.next

    def search(self, item):
        curr = self._head
        while curr != None:
            if curr.item == item:
                return True
            curr = curr.next

        return False


if __name__ == '__main__':
    s = SingleLink()
    print(s.is_empty())
    s.add(1)
    print(s.is_empty())
    s.append(1)
    print(s.travel())






链表与顺序表的对比

链表失去了顺序表随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大,但对存储空间的使用要相对灵活。

链表与顺序表的各种操作复杂度如下所示:

注意虽然表面看起来复杂度都是 O(n),但是链表和顺序表在插入和删除时进行的是完全不同的操作。链表的主要耗时操作是遍历查找,删除和插入操作本身的复杂度是O(1)。顺序表查找很快,主要耗时的操作是拷贝覆盖。因为除了目标元素在尾部的特殊情况,顺序表进行插入和删除时需要对操作点之后的所有元素进行前后移位操作,只能通过拷贝和覆盖的方法进行。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值