Python描述数据结构之单链表篇

前言

  本篇章主要介绍线性表,并用Python实现单链表的基本操作。

1. 线性表

  线性表 ( L i n e (Line L i s t ) List) 是具有相同数据类型的 n ( n 0 ) n(n\geq0) 个数据元素的有限序列。
L = ( a 1 , a 2 , . . . , a i , . . . , a n ) L=(a_1,a_2,...,a_i,...,a_n)   其中, a 1 a_1 称为表头元素, a n a_n 称为表尾元素,除表头元素外,每一个元素有且仅有一个直接前驱元素,除表尾元素外,每一个元素有且仅有一个直接后继元素。
在这里插入图片描述
  线性表的顺序存储结构称为顺序表,链式存储结构称为链表。由于顺序表在Python中和列表是一样的,其基本操作和列表的也一样,这里就不在过多叙述,主要介绍链表。

2. 单链表

  单链表中的每个结点除存放元素自身的信息外,还存放一个指向其后继元素的指针,其中data为数据域,存放数据元素,next为指针域,存放其后继结点的地址。结点的样子就是下面酱紫:在这里插入图片描述

  单链表的节点定义如下:

class LinkNode(object):
    def __init__(self, data=None, next=None):
        self.data = data
        self.next = next

  利用单链表可以解决顺序表需要大量连续存储单元的缺点,但单链表附加指针域,也存在浪费存储空间的缺点。由于单链表中的元素离散地分布在存储空间中,所以单链表是非随机存取的存储结构,即不能直接找到表中某个特定的结点,查找某个特定的结点时,需要从头开始遍历,依次查找。
  通常用头指针来表示一个单链表,头结点的数据域为None,指针域指向线性表的第一个元素结点。在这里插入图片描述

3. 基本操作

在这里插入图片描述
在这里插入图片描述
  这里简单举个两个栗子:比如我要插入个结点,就是上面那个数据元素为 a i a_i 的结点,这时我需要把这个结点的next域指向数据元素为 a 1 a_1 的结点,然后头结点(就是前面第一个结点)的next域指向这个结点(中间红色的连接就断开了);如果是在尾部插入结点,直接将尾部结点的next域指向这个结点即可。再比如我又想删除一个结点,就删除元素为 a 1 a_1 的那个结点吧,我需要将元素为 a 1 a_1 的那个结点的next域所指向的结点(元素为 a 2 a_2 的结点)“赋给”其前面结点(这里是头结点)的next域,换句话说就是头结点的next域指向元素为 a 2 a_2 的结点。在用Python描述数据结构时, = = 理解为指向更合适。
  下面的头插法和尾插法创建单链表时,创建出的单链表元素顺序正好是相反的,注意观察操作。

操作名称 操作说明
InsertInHead(val_list) 头插法创建单链表
InsertInTail(val_list) 尾插法创建单链表
IsEmpty() 判断单链表是否为空
LengthList() 返回单链表的长度
TraverseList() 打印出单链表里的数据元素
InsertInPosition(pos, data) 在指定位置插入
SearchWithPosition(pos) 按位置查找结点
SearchWithVal(data) 按值查找结点
RemoveWithPosition(pos) 移除指定位置的结点
RemoveWithVal(data) 移除指定值的结点

  书上有关基本操作的具体流程一定要熟记,本篇代码建议和书一起食用。

4. 代码实现

class SingleLinkList(object):
    def __init__(self):
        self.__head = LinkNode(None)

    def InsertInHead(self, val_list):
        """
        头插法, 将一个数组转换成单链表
        :param val_list:
        :return:
        """
        prehead = self.__head
        for val in val_list:
            new_node = LinkNode(val)
            if self.IsEmpty():
                prehead.next = new_node
            else:
                new_node.next = prehead.next
                prehead.next = new_node

    def InsertInTail(self, val_list):
        """
        尾插法, 将一个数组转换成单链表
        :param val_list:
        :return:
        """
        prehead = self.__head
        for val in val_list:
            new_node = LinkNode(val)
            prehead.next = new_node
            prehead = prehead.next

    def IsEmpty(self):
        """
        判断单链表是否为空, 空表返回True
        :return:
        """
        if self.__head.next is None:
            return True

    def LengthList(self):
        """
        返回单链表的长度
        :return:
        """
        prehead = self.__head
        count = 0
        if self.IsEmpty():
            return count
        while prehead.next:
            count += 1
            prehead = prehead.next
        return count

    def TraverseList(self):
        """
        遍历单链表, 并打印
        :return:
        """
        prehead = self.__head
        if self.IsEmpty():
            print('链表为空!')
            return 0
        while prehead.next:
            prehead = prehead.next
            print(prehead.data, end=' ')
        print('')

    def InsertInPosition(self, pos, data):
        """
        在某个位置插入
        :param pos: [1, LengthSingleLinkList + 1]
        :param data:
        :return:
        """
        prehead = self.__head
        new_node = LinkNode(data)
        if pos <= 0 or pos > self.LengthList() + 1:
            print('插入位置错误!')
            return 0
        count = 0
        while count < pos - 1:
            prehead = prehead.next
            count += 1
        new_node.next = prehead.next
        prehead.next = new_node

    def SearchWithPosition(self, pos):
        """
        按位置查找元素
        :param pos: [1, LengthSingleLinkList]
        :return:
        """
        prehead = self.__head
        if pos <= 0 or pos > self.LengthList():
            print('位置错误!')
            return -1
        count = 0
        while count < pos:
            prehead = prehead.next
            count += 1
        data = prehead.data
        return data

    def SearchWithVal(self, data):
        """
        按值查找元素
        :param data:
        :return:
        """
        prehead = self.__head
        count = 0
        while prehead.next:
            prehead = prehead.next
            count += 1
            if prehead.data == data:
                return count
        print('该节点不存在!')
        return -1

    def RemoveWithPosition(self, pos):
        """
        按位置移除元素
        :param pos: [1, LengthSingleLinkList]
        :return:
        """
        prehead = self.__head
        if pos <= 0 or pos > self.LengthList():
            print('位置错误!')
            return -1
        count = 0
        while count < pos - 1:
            prehead = prehead.next
            count += 1
        temp = prehead.next
        prehead.next = temp.next
        del temp

    def RemoveWithVal(self, data):
        """
        按值移除元素
        :param data:
        :return:
        """
        prehead = self.__head
        while prehead.next:
            prev = prehead
            prehead = prehead.next
            if prehead.data == data:
                prev.next = prehead.next
                return -1
        print('该节点不存在!')

  测试代码如下:

from LinkList import SingleLinkList


if __name__ == '__main__':
    l1 = SingleLinkList()
    print('头插法创建单链表l1: ', end='')
    l1.InsertInHead([1, 3, 5, 7, 9, 10])
    l1.TraverseList()

    l2 = SingleLinkList()
    print('尾插法创建单链表l2: ', end='')
    l2.InsertInTail([1, 3, 5, 7, 9, 10])
    l2.TraverseList()

    print('链表l2的长度为: %d' % l2.LengthList())

    print('在链表l2的第3个位置上插入值为2的节点: ', end='')
    l2.InsertInPosition(3, 2)
    l2.TraverseList()

    print('链表l2的第4个位置上的节点的值为: %d' % l2.SearchWithPosition(4))

    print('链表l2值为9的节点的位置为: %d' % l2.SearchWithVal(9))

    print('移除链表l2的第5个位置上的节点: ', end='')
    l2.RemoveWithPosition(5)
    l2.TraverseList()

    print('移除链表l2值为1的节点: ', end='')
    l2.RemoveWithVal(1)
    l2.TraverseList()

  测试代码如下:

在这里插入图片描述

结束语

  单链表是链表里面最基础的一个,理解了这个,其他链表也就不过如此了,最重要的是,链表的基本操作过程要记清楚,链表主要就是指针的指向,不要弄混或乱序。

猜你喜欢

转载自blog.csdn.net/qq_42730750/article/details/107869022