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

前言

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

1. 循环单链表

  循环单链表是在单链表的基础之上,将单链表的头结点地址存入了最后一个结点的指针域,即最后一个结点的next指针域不再是None,而是指向了头结点,所以循环单链表可以从表中的任意一个结点开始遍历整个链表。其他操作和单链表是一样的。
在这里插入图片描述

2. 基本操作

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

3. 代码实现

class CircularSingleLinkList(object):
    """
    与单链表不同的是, 循环单链表的最后一个节点的next指向头结点
    """
    def __init__(self):
        self.__head = LinkNode(None)
        self.__head.next = self.__head

    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
                new_node.next = self.__head
            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
            new_node.next = self.__head
            prehead = prehead.next

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

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

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

    def InsertInPosition(self, pos, data):
        """
        按位置插入
        :param pos: [1, LengthCircularSingleLinkList + 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 != self.__head:
            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 != self.__head:
            prev = prehead
            prehead = prehead.next
            if prehead.data == data:
                prev.next = prehead.next
                return -1
        print('该节点不存在!')

    def RemoveWithValAll(self, data):
        """
        按值移除元素(所有的)
        :param data:
        :return:
        """
        prehead = self.__head
        count = True
        while prehead.next != self.__head:
            prev = prehead
            prehead = prehead.next
            if prehead.data == data:
                prev.next = prehead.next
                count = False
        if count:
            print('该节点不存在!')

  测试代码如下:

from LinkList import CircularSingleLinkList


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

    l2 = CircularSingleLinkList()
    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()

  运行结果如下:

在这里插入图片描述

结束语

  循环单链表需要注意的就是尾结点的next指针域,所以在判别是不是尾结点的时候要注意这一点。当然,正是因为循环单链表是一个“环”,因此在任一位置上的插入和删除操作都是等价的,也就不需要刻意去判断是否是表尾了。

猜你喜欢

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