线性表:单向循环链表的基本操作

单向循环链表

单向循环链表只需要将普通的单链表首尾相连即可实现。

基本操作:

  • 判断列表是否为空:同单链表;
  • 头部/尾部插入元素:由于循环链表的优势,这一步操作将十分简单,只需要在尾部结点后直接插入即可,要注意的是如果采用尾插法,需要改变尾部节点
  • 弹出尾部元素:遍历即可
  • 指定位置添加元素:需要提前识别插入的位置是否为头部和尾部
  • 删除指定元素:需要判别删除的元素是否和尾部元素相同,如果相同则操作和'弹出尾部元素'操作类似,若不同则寻找元素,若元素不在链表中,需要提前识别异常。

Python实现:

class ListNode():
    def __init__(self, val, next=None):
        self.val = val
        self.next = next
        
class OneWayCircularLinkedList():
    def __init__(self):
        self.rear = None
    
    # 判断链表是否为空
    def is_empty(self):
        return self.rear is None
    
    # 在链表头部插入元素
    def prepend(self, val):
        p = ListNode(val)
        if self.is_empty():
            p.next = p
            self.rear = p
        else:
            p.next = self.rear.next
            self.rear.next = p
            
    # 在链表尾部插入元素
    def append(self, val):
        p = ListNode(val)
        if self.is_empty():
            p = p.next
            self.rear = p
        else:
            p.next = self.rear.next
            self.rear.next = p
            self.rear = self.rear.next
    
    # 计算链表长度
    def get_length(self):
        if self.is_empty():
            return 0
        cur = self.rear
        length = 1
        while cur.next != self.rear:
            length += 1
            cur = cur.next
        return length
    
    # 弹出尾部元素
    def pop_last(self):
        if self.is_empty():
            raise ValueError('self.rear 必须非空')
        # 链表只有一个元素时预先判断
        if self.rear.next == self.rear: 
            output = self.rear.val
            self.rear = None
            return output
        cur = self.rear
        while cur.next != self.rear:
            cur = cur.next
        output = cur.next.val
        cur.next = cur.next.next # 删除尾部节点
        self.rear = cur
        return output
    
    # 在指定位置添加元素
    def insert(self, position, element):
        p = ListNode(element)
        l = self.get_length()
        if position >= l or position < 0:
            raise ValueError('超出了链表长度范围!')
        
        # 判空
        if self.is_empty():
            if position > 0:
                raise ValueError('链表为空,且没有在位置0添加元素!')
            else:
                p.next = p
                self.rear = p
                return
        
        # 分三种情况添加元素
        if position == 0:
            self.prepend(element)
        elif position == l - 1:
            self.append(element)
        else:
            cur = self.rear
            while position > 0:
                cur = cur.next
                position -= 1
            p.next = cur.next
            cur.next = p
        
    # 删除指定元素
    def remove(self, element):
        if self.is_empty():
            raise ValueError('self.rear 必须非空')
        cur = self.rear
        flag = False # 标记是否链表含有指定元素
        if self.rear.val == element:
            flag = True
            if self.rear.next == self.rear: 
                output = self.rear.val
                self.rear = None
                return output
            else:
                cur = self.rear
                while cur.next != self.rear:
                    cur = cur.next
                cur.next = cur.next.next # 删除尾部节点
                self.rear = cur
        else:
            while cur.next.val != element and cur.next != self.rear:
                cur = cur.next
                if cur.next.val == element:
                    flag = True
                    
            if not flag:
                raise ValueError('链表中不存在该元素!')
            cur.next = cur.next.next
                
    
        
if __name__ == '__main__':
    def testfunction(node):
        nums = []
        cur = node.next
        while cur != node:
            nums.append(cur.val)
            cur = cur.next
        nums.append(cur.val)
        return nums
    
    sample = OneWayCircularLinkedList()
    for i in range(8):
        sample.prepend(i)
    print(testfunction(sample.rear))
    
    sample.append(2)
    print(testfunction(sample.rear))
    
    print(sample.get_length())
    
    print(sample.pop_last())
    
    sample.insert(1, 10)
    print(testfunction(sample.rear))

总结

不难发现,单向循环链表的优势在于头尾相连,此时尾端插入的效率较高。

猜你喜欢

转载自blog.csdn.net/a159357445566/article/details/109036825
今日推荐