python3实现单向循环链表

单向循环链表是单向链表的一个拓展,主要区别在于单向循环链表尾节点的next不再指向None,而是指向链表的头节点。

下面通过代码一步步实现单向循环链表并附上注释和测试,主要实现以下几个基本方法:

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

首先照例定义节点类对象:

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

然后开始写单向循环链表(Single Cyclic LInked List)的类:

class SCLL():
    ###别忘了先定义一个带默认值的头节点!!!
    def __init__(self, node = None):
        self.__head = node
        if self.__head:        #这里要注意和无循环链表的区别了
            node.next = self.__head   #如果头节点不为空,则使尾节点指向头节点
    
    def is_empty(self):
        return self.__head == None
    
    def length(self):
        if self.is_empty():
            return 0
        else:
            count = 1    #根据条件循环结束方式,使count从1开始计数
            cur = self.__head
            while cur.next != self.__head:
                count +=1
                cur = cur.next
            return count
    
    def travel(self):
        cur = self.__head
        if self.is_empty():
            return None
        else:
            while cur.next != self.__head:
                print(str(cur.item), end = " ")
                cur = cur.next
            # if cur.next == self.__head: 这里不需要再用if了,直接输出就好
            print(str(cur.item))

    def add(self, item):
        cur = self.__head
        node = Node(item)
        if self.is_empty():  #先判空,是的话直接添加
            self.__head = node
            node.next = self.__head
        else:
            while cur.next != self.__head: #链表非空的话,先遍历找到尾节点
                cur = cur.next
            node.next = self.__head  #在头部添加,注意赋值顺序
            self.__head = node
            cur.next = self.__head   #这里使遍历找到的尾节点重新指向新的头节点
            
    def append(self, item):
        cur = self.__head
        node = Node(item)
        if self.is_empty():  #照例先判空
            self.__head = node
            node.next = self.__head
        else:
            while cur.next != self.__head:  #遍历找到尾节点
                cur = cur.next
            cur.next = node     #在尾节点处添加,并指向头节点
            node.next = self.__head

    def insert(self, pos, item):
        cur = self.__head
        node = Node(item)
        if pos <= 0:    #pos<=0相当于头插法
            self.add(item)
        elif pos >= self.length(): #pos比length还大相当于尾插法
            self.append(item)
        else:
            pre_cur = None   #这里像单链表一样定义一个位于cur前一个的游标
            count = 0     #开始遍历,找到下标为pos的节点
            while count != pos:
                pre_cur = cur
                cur = cur.next
                count += 1
            node.next = pre_cur.next #遍历找到之后开始相互赋值了,注意先后顺序
            pre_cur.next = node           

    def remove(self, item):
        cur = self.__head
        node = Node(item)
        if self.is_empty():  #先判空,是的话直接return
            return
        else:
            pre_cur = None
            while cur.item != node.item:  #这里先开始遍历
                if cur.next == self.__head:  #如果到头了还没找到那就return了,注意要先判断
                    return
                pre_cur = cur
                cur = cur.next
            if ((pre_cur == None) and (cur.next == self.__head)): #特殊情况1:只有一个节点时
                cur = None
            elif ((pre_cur == None) and (cur.next != self.__head)): #特殊情况2:删除首节点
                # self.__head = cur.next   
                tail = cur   #定义一个临时游标,用于遍历找到尾节点
                while tail.next != self.__head:
                    tail = tail.next
                tail.next = cur.next    #注意要先操作临时游标,此时的cur还是首节点
                self.__head = cur.next  #让self.__head指向首节点的next
                ### 下面两行是要删除的节点为尾节点的情况,验证可知此情况可当做一般情况处理
            # elif ((pre_cur != None) and (cur.next == self.__head)):
            #     pre_cur.next = cur.next
            else:   #一般情况下处理节点
                pre_cur.next = cur.next              

    def search(self, item):
        cur = self.__head
        if self.is_empty(): #链表为空时直接返回
            return False
        else:
            node = Node(item)
            while cur.item != node.item:  #遍历寻找
                if cur.next == self.__head:  #到尾节点时返回
                    return False
                cur = cur.next                
            return True

下面开始测试:

if __name__ == "__main__":
    #定义单向循环链表scll
    scll = SCLL()

    #测试尾插法
    scll.append(0)
    scll.append(1)
    scll.append(2)
    scll.append(3)
    print("链表scll长度?\n" + str(scll.length()) + "\n")
    print("遍历链表scll:")
    scll.travel()
    print("\n")
    
    #测试insert,注意每插入一个新的元素,后面的元素下标都变了
    scll.insert(0, -0.5)
    print("遍历链表scll:")
    scll.travel()
    print("\n")
    scll.insert(1, 555)
    scll.insert(3, 555)
    scll.insert(6, 2.5)
    print("遍历链表scll:")
    scll.travel()
    print("\n")

    #测试头插法
    scll.add(-1)
    scll.add(-2)
    print("遍历链表scll:")
    scll.travel()
    print("\n")

    #测空
    print("链表scll是否为空?\n" + str(scll.is_empty()) + "\n")

    #测长
    print("链表scll长度?\n" + str(scll.length()) + "\n")

    #遍历打印
    print("遍历链表scll:")
    scll.travel()
    print("\n")

    #测试search,返回True或False
    print(str(scll.search(555)) + "\n")
    print(str(scll.search(-2)) + "\n")
    print(str(scll.search(3)) + "\n")
    print(str(scll.search(123456)) + "\n")

    #测试remove中间节点,结束后打印
    scll.remove(555)
    print("遍历链表scll:")
    scll.travel()
    print("\n")

    #测试remove头节点,并打印
    scll.remove(-2)
    print("遍历链表scll:")
    scll.travel()
    print("\n")

    #测试remove尾节点并打印
    scll.remove(3)
    print("遍历链表scll:")
    scll.travel()
    print("\n")

    #测试remove一个不存在的节点
    scll.remove(123456)
    print("遍历链表scll:")
    scll.travel()
    print("\n")

可以看到测试部分基本包含了每个方法的特殊情况,下面运行一下看看结果如何:

链表scll长度?
4

遍历链表scll:
0 1 2 3


遍历链表scll:
-0.5 0 1 2 3


遍历链表scll:
-0.5 555 0 555 1 2 2.5 3


遍历链表scll:
-2 -1 -0.5 555 0 555 1 2 2.5 3


链表scll是否为空?
False

链表scll长度?
10

遍历链表scll:
-2 -1 -0.5 555 0 555 1 2 2.5 3


True

True

True

False

遍历链表scll:
-2 -1 -0.5 0 555 1 2 2.5 3


遍历链表scll:
-1 -0.5 0 555 1 2 2.5 3


遍历链表scll:
-1 -0.5 0 555 1 2 2.5


遍历链表scll:
-1 -0.5 0 555 1 2 2.5

结果如期。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值