单链表及python代码实现

1 单链表

单链表由两部分组成:元素域与链接域。 元素域保存作为表元素的数据项,链接域保存同一个表里的下一个结点的标识。
图1.1 单链表的结点和单链表
单链表有以下特点:

  • 一个单链表由一些具体的表结点组成;
  • 每个结点是一个对象,由自己的标识,也称为该结点的链接;
  • 结点之间通过结点链接建立起单向的顺序链接;
  • 在python中,通常用None值作为单链表中最后一个结点的链接域。
    为方便讨论,现在定义一个简单的表结点类:
class LNode:
    def __init__(self,elem,next_=None):
        self.elem=elem
        self.next=next_

1.1 基本链表操作

1.1.1 创建空链表:只需要把表头变量设置成空链接,在python语言中设置成为None。
1.1.2 删除链表:应丢弃这个链表里的所有结点。在python语言中,只需要将表指针赋值为None,就抛弃了链表中的所有结点。python解释器的存储管理系统会自动回收不用的存储。
1.1.3 判断表是否为空:将表头变量的值与空链接比较,在python语言中,就是检查相应的变量是否为None。
1.1.4 判断表是否会满:一般而言链表不会满。

1.2 加入元素

1.2.1 表首端插入: 三步即可完成:

  • 创建一个新节点并存入数据;
  • 把原链表首节点的链接域存入新结点的链接域next。
  • 修改表头变量,使之指向新节点。
    这里写图片描述
    示例代码段:
q=LNode(13)
q.next=head.next
head=q

1.2.2 表中间元素的插入(包括链表末尾插入): 设变量pre已指向要插入元素位置的歉前一结点,操作也分为三步:

  • 创建一个新节点并存入数据;
  • 把pre所指结点的next域的值存入新节点的链接域next;
  • 修改pre的next域,使之指向新结点;
    这里写图片描述
    示例代码段
q=LNode(12)
q.next=pre.next
pre.next=q

1.3 删除元素

1.3.1 删除表首元素:删除表中第一个元素对应于删除表的第一个结点,为此只需要修改表头指针,令其指向表中的第二个结点。
示例代码段

head=head.next

1.3.2 一般元素的情况删除:一般情况删除须先找到删除元素所在结点的前一结点,设用变量pre指向,然后修改pre的next域,使之指向被删除域的下一结点。
示例代码段

pre.next=pre.next.next

这里写图片描述

1.4 扫描、定位和遍历

1.4.1 扫描:由于单链表只有一个方向的链接,开始情况下只有表头变量在掌握中,所以对表的内容的检查只能从表头变量开始,沿着表中链接逐步进行。这种行为称之为链表的扫描。

  • 按下标定位:按Python惯例,链表首结点的元素应看做下标为0,其他元素依次排列,确定第i个元素所在结点的操作称为按下标定位。代码示例段如下:
p=head
while p is not None and i > 0:
    i-=1
    p=p.next
  • 按元素定位:假设在链表中需要找到满足谓词pred的元素,示例代码段如下:
p=head
while p is not None and not pred(p.elem):
    p=p.next
  • 完整的遍历
p=head
while p is not None:
    print p.elem
    p=p.next

1.5 链表操作的时间复杂度

  • 创建空表:O(1)
  • 删除表:O(1)
  • 判断空表:O(1)
  • 加入元素(都需要加一个T()分配时间):
  • 首端加入元素,O(1)
  • 尾端加入元素,O(n)
  • 定位加入元素,O(n),平均情况和最坏情况
  • 删除元素:
  • 首端删除元素:O(1)
  • 尾端删除元素:O(n)
  • 定位删除元素:O(n),平均情况和最坏情况
  • 其他删除:通常需要扫描整个表或其一部分

1.6 LList类的定义,初始化函数和简单操作

现在基于结点类LNode定义一个单链表类,只有一个引用链接结点的_head域,初始化为None表示建立的是一个空表。

class LList:
    def __init__(self):
        self._head=None

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

    #insert element on the beginning of the list    
    def prepend(self):           
         self._head=LNode(elem,self._head)

    def pop(self):
        if self._head is None:   #if list is none, raise exception
            raise Error
        e=self._head.elem
        self._head=self._head.next
        return e

    # insert element on the end of the List
    def append(self,elem):
        if self._head is None:
            self._head=LNode(elem)
            return 
        p=self._head
        while p is not None:
            p=p.next
        p.next=LNode(elem)

    # delete the last node and return it's value
        def pop_last(self):
            if self._head is None:
                raise ExceptionError
            p=self._head
            if p.next is None:
                e=p.elem
                self._head=None
                return e
            while p.next.next is not None:
                p=p.next
            e=p.next.elem
            p.next=None
            return e
    #basic scan element in the List
    def find(self,pred):
        p=self._head
        while p is not None:
            if pred(p.elem):
                return p.elem
            p=p.next
    # print all elem in the list
    def printall(self):
        p=self._head
        while p is not None:
            print p.elem 
            if p.next is not None:
                print ','
            p=p.next
        print ''

参考文献:数据结构与算法:Python语言描述

猜你喜欢

转载自blog.csdn.net/qingyangfeng/article/details/80453225