数据结构(三)单向循环链表的的分析与python代码实现

版权声明:尊重原作者,转载请在文章头部注明网址。 https://blog.csdn.net/u013034226/article/details/85797511

概念

单链表的一个变形是单向循环链表,链表中最后一个节点的next域不再为None,而是指向链表的头节点。

节点包含两个域:元素域和链接域(下一个节点),尾节点next指向第0个节点,当链表只有一个节点时,自己的next指向自己,基于单链表的基础上,增加考虑首节点和尾节点的情况。

结构

python代码实现

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

class CycleLinkList(object):
    def __init__(self):
        self.head = None


    def is_empty(self):
        """链表是否为空"""
        return self.head is None


    def length(self):
        """链表长度"""
        if self.is_empty():
            return 0
        cur = self.head
        n = 1
        while cur.next != self.head:
            n += 1
            cur = cur.next
        # 至此除了尾节点外,所有节点都被数了一次

        return n

    def travel(self):
        """遍历整个链表"""
        if self.is_empty():
            return

        cur = self.head
        while cur.next != self.head:
            print(cur.item,end="->")
            cur = cur.next
        # 至此,cur指向尾节点,cur本身还未被打印
        print(cur.item)


    def add(self, item):
        """链表头部添加元素"""
        node = Node(item)
        # 若没有尾节点(链表为空),head指向新节点,新节点next指向自己
        if self.is_empty():
            self.head = node
            node.next = node
        else:
            # 1 找到尾节点cur
            cur = self.head
            while cur.next != self.head:
                cur = cur.next
            # 至此,cur指向尾节点
            #2 新节点next指向原首节点
            node.next = self.head
            #3 head指向新节点
            self.head = node
            #4 尾节点next指向新节点
            cur.next = node



    def append(self, item):
        """链表尾部添加元素"""

        # 若链表为空,则直接头部添加
        if self.is_empty():
            self.add(item)
            return

        # 1 遍历查找尾节cur
        cur = self.head
        while cur.next != self.head:
            cur = cur.next
        # 至此cur指向当前链表的尾节点
        # 2 cur的next指向新节点
        node = Node(item)
        cur.next = node
        # 3 新节点next指向首节点
        node.next = self.head


    def insert(self, pos, item):
        """指定位置添加元素"""
        if pos <=0 :
            self.add(item)
        elif pos >= self.length():
            self.append(item)
        else:
            # 1 遍历查找带插入位置的前一个节点cur
            cur = self.head
            for i in range(pos - 1):
                cur = cur.next
            # 至此,cur指向的就是带插入位置的前一个节点
            # 2 新节点的next指向cur的next
            node = Node(item)
            node.next = cur.next
            # 3 cur的next指向新节点
            cur.next = node

    def remove(self, item):
        """删除节点"""
        if self.is_empty():
            return
        cur = self.head
        pre = None
        # 1 遍历查找找到待删节点并记录前一个节点
        while cur.next != self.head:
            if cur.item == item:
                # 2 若有前一个节点,pre的next指向cur的next
                if pre is not None:
                    pre.next = cur.next
                else:
                    # 否则(待删节点是首节点),
                    # 1)遍历查找尾节点tail
                    tail = self.head
                    while tail.next != self.head:
                        tail = tail.next
                    # 2) head指向cur的next
                    self.head = cur.next
                    # 3) tail的next指向head
                    tail.next = self.head
                return
            pre = cur
            cur = cur.next
        # 至此cur指向尾节点,尾节点还未判断是否是待删节点
        # 3 判断尾节点是否是待删节点
        if cur.item == item:
            # 若有前一个节点,pre的next指向cur的next
            if pre is not None:
                pre.next = cur.next
            # 否则(待删节点是链表唯一节点),head指向None
            else:
                self.head = None

    def search(self, item):
        """查找节点是否存在"""
        if self.is_empty():
            return False

        cur = self.head
        while cur.next != self.head:
            if cur.item == item:
                return True
            cur = cur.next
        # 至此,除了尾节点外所有节点都找过了,还没找到
        # 判断尾节点是否是待查节点
        if cur.item == item:
            return True
        return  False

# 测试代码
if __name__ == '__main__':
    cl = CycleLinkList()
    cl.add(1)
    cl.add(2)
    cl.add(3)
    cl.travel()
    # 结果3-2-1-
    cl.append("abc")
    cl.append("def")
    cl.append("ghi")
    cl.travel()
    # 结果3-2-1-abc-def-ghi-
    cl.insert(-1, "xx")
    cl.insert(99, "yy")
    cl.insert(3, "zz")
    cl.travel()
    # 结果xx-3-2-zz-1-abc-def-ghi-yy-
    cl.remove("xx")
    cl.remove("yy")
    cl.remove(1)
    cl.remove(90)
    cl.travel()
    # 结果3-2-zz-abc-def-ghi-
    print(cl.search(3))
    # 结果True
    print(cl.search("zz"))
    # 结果True
    print(cl.search(380))
    # 结果False

复杂度

循环链表头部添加O(n),循环链表尾部添加O(n),循环链表中间位置添加O(n),循环链表删除O(n)。

猜你喜欢

转载自blog.csdn.net/u013034226/article/details/85797511