3. 单向链表

1. 链表的定义:

  链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是不像顺序表一样连续存储数据,而是在每一个节点(数据存储单元)里存放下一个节点的位置信息(即地址)。

  顺序表的构建需要预先知道数据大小来申请连续的存储空间,而在进行扩充时又需要进行数据的搬迁,所以使用起来并不是很灵活。

  链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。

2. 单向链表:

  (1)单向链表定义:

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

  表元素域elem用来存放具体的数据。

  链接域next用来存放下一个节点的位置(python中的标识)

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

  (2)节点实现:

class Node(object):
    """单链表的结点"""
    def __init__(self, elem):
        # elem存放数据元素
        self.elem = elem
        # next是下一个节点的标识
        self.next = None

  (3)单链表操作: 

      is_empty():       链表是否为空

      length():       链表长度

      travel():        遍历整个链表

      add(item):       链表头部添加元素

      append(item):   链表尾部添加元素

      insert(pos, item):  指定位置添加元素

      remove(item):     删除节点

      search(item):   查找节点是否存在

  (4)单向链表的实现:

class SingleLinkList(object):
    """单链表"""
    def __init__(self, node=None):  # 默认参数node=None
        self.__head = node           # 私有属性__head=>链表头

    def is_empty(self):
        """判断链表是否为空"""
        return self.__head == None

    def length(self):
        """链表长度"""
        # cur初始时指向头节点,类似于游标,用来移动遍历节点
        cur = self.__head
        # 记录节点数量,初始为0
        count = 0
        # 尾节点指向None,当未到达尾部时,循环结束
        while cur != None:
            count += 1
            # 将cur后移一个节点
            cur = cur.next
        return count

    def travel(self):
        """遍历链表"""
        cur = self.__head
        while cur != None:
            print(cur.elem, end=" ")    # 打印元素的值
            cur = cur.next              # cur后移
        print("")   #换行

  (5)头部添加元素:

      

    def add(self, item):
        """头部添加元素,头插法"""
        # 先创建一个保存item值的节点
        node = Node(item)
        # 将新节点的链接域next指向头节点,即__head指向的位置
        node.next = self.__head
        # 将链表的头__head指向新节点
        self.__head = node

  (6)尾部添加元素:  

    def append(self, item):
        """尾部添加元素,尾插法"""
        node = Node(item)
        # 先判断链表是否为空,若是空链表,则将__head指向新节点
        if self.is_empty():
            self.__head = node
        # 若不为空,则找到尾部,将尾节点的next指向新节点
        else:
            cur = self.__head
            while cur.next != None: #此时循环条件变了
                cur = cur.next
            cur.next = node

  (7)指定位置添加元素:

    def insert(self, pos, item):
        """指定位置添加元素
        : param   pos 从0开始
        """
        # 若指定位置pos为第一个元素之前,则执行头部插入
        if pos <= 0:
            self.add(item)
        # 若指定位置超过链表尾部,则执行尾部插入
        elif pos > (self.length()-1):   # 不能包含等号=
            self.append(item)
        # 找到指定位置
        else:
            node = Node(item)
            count = 0
            # pre用来指向指定位置pos的前一个位置pos-1,初始从头节点开始移动到指定位置
            pre = self.__head
            while count < (pos-1):
                count += 1
                pre = pre.next      # 循环结束后,pre指向pos-1位置
            # 先将新节点node的next指向插入位置的节点
            node.next = pre.next
            # 将插入位置的前一个节点的next指向新节点
            pre.next = node

  (8)删除节点:

    def remove(self, item):
        """删除节点,也可以只用一个游标"""
        cur = self.__head
        pre = None
        while cur != None:
            # 找到了指定元素
            if cur.elem == item:
                # 先判断此节点是否是头结点
                # 如果第一个就是删除的节点
                if cur == self.__head:      # 或者if not pre:
                    # 将头指针指向头节点的后一个节点
                    self.__head = cur.next
                else:
                    # 将删除位置前一个节点的next指向删除位置的后一个节点
                    pre.next = cur.next
                break
            else:
                # 继续按链表后移节点,注意移动的先后顺序
                pre = cur
                cur = cur.next

  (9)查找节点是否存在:

    def search(self, item):
        """链表查找节点是否存在,并返回True或者False"""
        cur = self.__head
        while cur != None:
            if cur.elem == item:
                return True
            else:
                cur = cur.next
        return False

  (10)测试:

if __name__ == "__main__":
    ll = SingleLinkList()
    print(ll.is_empty())    # True
    print(ll.length())      # 0

    ll.append(1)
    print(ll.is_empty())    # False
    print(ll.length())      # 1

    ll.append(2)
    ll.add(8)
    ll.append(3)
    ll.append(4)
    ll.append(5)
    ll.append(6)
    ll.travel()         # 8 1 2 3 4 5 6

    ll.insert(-1, 9)
    ll.travel()         # 9 8 1 2 3 4 5 6
    ll.insert(3, 100)
    ll.travel()         # 9 8 1 100 2 3 4 5 6
    ll.insert(10, 200)
    ll.travel()         # 9 8 1 100 2 3 4 5 6 200
    ll.remove(100)
    ll.travel()         # 9 8 1 2 3 4 5 6 200
    ll.remove(9)
    ll.travel()         # 8 1 2 3 4 5 6 200
    ll.remove(200)
    ll.travel()         # 8 1 2 3 4 5 6

  (11)运行结果(只需将以上代码全部组合在一起运行即可):

      

猜你喜欢

转载自www.cnblogs.com/si-lei/p/9261376.html