线性表(单向循环链表(动图解析))


这一部分虽然大部分原理与单向链表相似。但是比单向链表多分析“头节点、只有一个节点、中间节点、尾部节点”,针对较为复杂的操作,进行了详细的分析。其余简单的部分可以参考“单向链表”。

单向循环链表

单链表的一个变形是单向循环链表,链表中最后一个节点的next域不再为None,而是指向链表的头节点。
在这里插入图片描述

单向循环链表的操作

节点定义

链表中最后一个节点的next域不再为None,而是指向链表的头节点。因此它的节点定义与 “单向链表与双向链表明显不同”
在这里插入图片描述

// An highlighted block
class SingleLinkList(object):
    """单链表的结点"""
    def __init__(self,item=None,node=None):
        self.item = item
        self.next = None
        self._head = node
        if node:        
            node.next=node
计算链表长度

判断cur的下一个节点是否是头结点
在这里插入图片描述

// An highlighted block
    """链表长度"""
    def length(self):
        if self.is_empty():
            return 0
        cur = self._head  # cur初始时指向头节点
        count = 1
        while cur.next != self._head:   #判断cur的下一个节点是否为头结点
            count=count+1
            cur=cur.next  # 将cur后移一个节点
        return count
遍历链表元素

判断cur的下一个节点是否是头结点

// An highlighted block
"""遍历链表"""
    def travel(self):
        #判断是否为空链表
        if self.is_empty():
            return
        cur = self._head
        while cur.next != self._head:
            print(cur.item,end="\t")
            cur = cur.next
        #退出循环时,cur指向末尾节点,但是节点鹅元素未被打印
        print(cur.item)
在头部添加元素

首先使用cur遍历所有元素,找到尾节点,再将尾节点next域指向新添加的元素
在这里插入图片描述

// An highlighted block
    """头部添加元素"""
    def add(self, item):
        node = Single_CircleLinkList(item)
        if self.is_empty():
            self._head=node
            node.next=node
        else:
            cur=self._head
            while cur.next!=self._head:
                cur=cur.next
            #退出循环,cur指向尾节点
            node.next=self._head
            self._head=node
            cur.next=self._head
        node = Single_CircleLinkList(item)
        node.next = self._head
        self._head = node
在尾部添加元素

首先使用cur遍历所有元素,找到尾节点,再将尾节点next域指向新添加的元素,新元素的next域指向头结点
在这里插入图片描述

// An highlighted block
"""尾部添加元素"""
    def append(self, item):
        node = Single_CircleLinkList(item)
        if self.is_empty():  # 先判断链表是否为空,若是空链表,则将_head指向新节点
            self._head = node  # 若不为空,则找到尾部,将尾节点的next指向新节点
            node.next=node
        else:
            cur = self._head
            while cur.next!= self._head:  # 判断下一个节点是否为None
                cur = cur.next
            node.next=self._head
            cur.next = node
删除元素

这一部分原理跟单链表相似,但是在具体分析中,掺杂了空链表、第一个元素、只有一个节点的删除、中间元素的删除和尾部元素的删除,因此单独拿出来分析。其余的在“单向循环链表”中提到的,由于分析较为简单,没有单独分析。

 """删除一个节点"""
 #单独说明  引入尾部节点 rear,尾结点是指链表中最后一个节点,在单链表中,尾结点的指针一般为空,即没有保存其他节点的存储位置信息。但在双向链表中,尾结点一般指向链表中第一个节点。
 #引入rear的原因是 通过rear游标找到最后一个节点
    def remove(self, item):
        # 若链表为空,则直接返回
        if self.is_empty():
            return
        cur = self._head
        pre = None
        while cur.next != self._head:
            if cur.item == item:
                # 先判断此节点是否为头结点
                if cur == self._head:
                    #头结点的情况
                    #先找尾节点,然后由尾节点找到指向的头节点
                    rear = self._head  
                    rear = rear.next
                    while rear.next!=self._head:
                        rear = rear.next
                    self._head = cur.next
                    rear.next=self._head
                else:
                    #中间节点
                    pre.next = cur.next
                return
            else:
                pre = cur
                cur = cur.next
        #退出循环,cur指向尾节点
        if cur.item==item:
            if cur==self._head:
                #链表只有一个节点
                self._head=None
            else:
                pre.next=cur.next
var foo = 'bar';
修改元素

找到指定位置的元素,然后用指定的值去修改

// An highlighted block
    def change(self, pos,num,item=None):
        self.item = item
        # node = SingleLinkList(item)
        cur = self._head
        count = 0
            # 通过计数判断是否移动到指定位置的前一个位置
        while count < (pos - 1):
            count += 1
            cur = cur.next
        cur.item =num
元素反转
// An highlighted block
class Node(object):
    def __init__(self, item=None, next=None):
        self.item = item
        self.next = next

    def rev(link):
        pre = link
        cur = link.next
        pre.next = None
        while cur:
            temp = cur.next
            cur.next = pre
            pre = cur
            cur = temp
        return pre

if __name__ == '__main__':
    link = Node(1, Node(2, Node(3, Node(4, Node(5, Node(6, Node(7, Node(8, Node(9)))))))))
    root=link
    while root:
        print(root.item,end="\t")
        root = root.next
    print(end="\n")
    root = link.rev()
    while root:
        print(root.item,end="\t")
        root = root.next

在这里插入图片描述

程序运行

// An highlighted block
"""单链表的结点"""
class SingleLinkList(object):
    def __init__(self,item=None,node=None):
        self.item = item
        self.next = None
        self._head = node
        if node:
            node.next=node

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

    """链表长度"""
    def length(self):
        cur = self._head  # cur初始时指向头节点
        count = 0
        while cur != None:  # 尾节点指向None,当未到达尾部时
            count=count+1
            cur=cur.next  # 将cur后移一个节点
        return count

    """遍历链表"""
    def travel(self):
        cur = self._head
        while cur != None:
            print(cur.item,end="\t")
            cur = cur.next
        print(end="\n")

    """尾部添加元素"""
    def append(self, item):
        node = SingleLinkList(item)
        if self.is_empty():  # 先判断链表是否为空,若是空链表,则将_head指向新节点
            self._head = node  # 若不为空,则找到尾部,将尾节点的next指向新节点
        else:
            cur = self._head
            while cur.next!= None:  # 判断下一个节点是否为None
                cur = cur.next
            cur.next = node

    """头部添加元素"""
    def add(self, item):
        node = SingleLinkList(item)
        node.next = self._head
        self._head = node

    """在指定位置添加元素
    添加的元素是 (2,50),则pos=2
    """
    def insert(self, pos, item):
        # 判断指定位置是进行头部添加还是尾部添加
        if pos <= 0:
            self.add(item)
        elif pos > (self.length() - 1):
            self.append(item)
        else:
            node = SingleLinkList(item)
            cur = self._head
            count = 0
            # 通过计数判断是否移动到指定位置的前一个位置
            while count < (pos - 1):
                count += 1
                cur = cur.next
            node.next = cur.next
            cur.next = node

    """查找节点是否存在"""
    def search(self, item):
        cur = self._head
        while cur != None:
            if cur.item == item:
                print("True")
                return True
            else:
                cur = cur.next
        print("False")
        return False

    """删除一个节点"""
    def remove(self, item):
        # 若链表为空,则直接返回
        cur = self._head
        pre = None
        # 若头节点的元素就是要查找的元素item
        while cur != None:
            if cur.item == item:
                # 先判断此节点是否为头结点
                if cur == self._head:
                    self._head = cur.next
                else:
                    pre.next = cur.next
                break
            else:
                pre = cur
                cur = cur.next

    """在指定位置添加元素
        添加的元素是 (2,50),则pos=2
        """

    def insert(self, pos, item):
        # 判断指定位置是进行头部添加还是尾部添加
        if pos <= 0:
            self.add(item)
        elif pos > (self.length() - 1):
            self.append(item)
        else:
            node = SingleLinkList(item)
            cur = self._head
            count = 0
            # 通过计数判断是否移动到指定位置的前一个位置
            while count < (pos - 1):
                count += 1
                cur = cur.next
            node.next = cur.next
            cur.next = node

    '''修改元素'''
    def change(self, pos,num,item=None):
        self.item = item
        # node = SingleLinkList(item)
        cur = self._head
        count = 0
            # 通过计数判断是否移动到指定位置的前一个位置
        while count < (pos - 1):
            count += 1
            cur = cur.next
        cur.item =num
        
if __name__=="__main__":
    a=SingleLinkList()
    print(a.is_empty())
    print(a.length())
    #在尾部增加元素
    a.append(1)
    print(a.is_empty())
    print(a.length())
    a.append(2)
    a.append(3)
    a.append(4)
    a.append(5)
    a.append(6)
    a.travel()
    #在头部增加元素
    a.add(20000)
    a.travel()
    # # 在指定位置插入
    a.insert(3,50)
    a.travel()
    print(a.length())
    # #删除元素
    a.remove(20000)
    a.travel()
    # #查找元素
    a.search(50)
    a.search(10000)
    a.search(30000)
    a.insert(3,80)
    a.travel()
    a.change(3,100)
    a.travel()

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_42567027/article/details/107093886