数据结构02:单链表、循环双端链表(Python实现)

线性结构:内存连续,能通过下标访问。
链式结构:内存不连续,不能通过下标访问,查找元素需要从头到尾遍历。

单链表

单链表:有一个一个节点,用指针方式串起来,有root节点,是入口,第一个节点为首节点(Head),有尾节点(Tail)

#Node节点,表示每一个元素
class Node(object):
    #定义节点,两个值:value,next
    def __init__(self, value=None, next=None):
        self.value, self.next = value, next

#定义单链表
class LinkedList(object):
    #初始化,None为无限
    def __init__(self, maxsize=None):
        self.maxsize = maxsize
        #根节点
        self.root = Node()
        #长度
        self.length = 0
        #最后一个节点
        self.tailnode = None
    
    #返回记录的长度
    def __len__(self):
        return self.length
    
    #构造一个节点,再用最后一个节点指向他,O(1)
    def append(self, value):
        #判断是否超过了最大值,若超过了,抛出异常
        if self.maxsize is not None and len(self) > self.maxsize:
            raise Exception('FUll')
        node = Node(value)
        tailnode = self.tailnode
        if tailnode is None:
            self.root.next = node
        else:
            tailnode.next = node
        #更新尾节点
        self.tailnode = node
        self.length += 1
    
    #往左边节点插入,O(1)
    def appendleft(self, value):
        #头结点headnode
        headnode = self.root.next
        #构造新节点
        node = Node(value)
        self.root.next = node
        node.next = headnode
        self.length += 1
    
    #遍历,从Head节点到tail节点
    def iter_node(self):
        currnode = self.root.next
        while currnode is not self.tailnode:
            yield currnode
            #更新节点
            currnode = currnode.next
        yield currnode
    
    #__iter__方法
    def __iter__(self):
        for node in self.iter_node():
            yield node.value
    
    #删除,将其前一个节点的next指向被查询节点的下一个即可,复杂度O(n)
    def remove(self, value):
        prevnode = self.root
        currnode = self.root.next
        while currnode.next is not None:
            if currnode.value == value:
                #上一个节点的元素指向下一个节点的下一个元素
                prevnode.next = currnode.next
                #NOTE:注意更新tailnode
                if currnode is self.tailnode:
                	self.tailnode = prevnode
                del currnode
                self.length -= 1
                return 1
           	else:
           		#更新prevnode
           		prevnode = currnode
      	return -1
    
    #查找操作,复杂度O(n)
    def find(self, value):
        index = 0
        for node in self.iter_node():
            if node.value == value:
                return index
            index += 1
        return -1
    
    #拿掉第一个节点
    def popleft(self):
        if self.root.next is None:
            raise Exception('pop from empty LinkedList')
        headnode = self.root.next
        self.root.next = headnode.next
        self.length -= 1
        value = headnode.value
        del headnode
        #返回value值
        return value
    
    #清除操作
    def claer(self):
        for node in self.iter_node():
            del node
        self.root.next = None
        self.length = 0

        
#测试脚本        
def test_linked_list():
    ll = LinkedList()
    ll.append(0)
    ll.append(1)
    ll.append(2)
    
    #断言
    assert len(ll) == 3
    assert ll.find(2) == 2
    assert ll.find(3) == -1
    
    ll.remove(0)
    assert len(ll) == 2
    assert ll.find(0) == -1
    
    assert list(ll) ==[1, 2]
    
    ll.appendleft(0)
    assert list(ll) == [0, 1, 2]
    assert len(ll) == 3
    
    headvalue = ll.popleft()
    assert headvalue == 0
    assert len(ll) == 2
    assert list(ll) == [1, 2]
    
    ll.claer()
    assert len(ll) == 0

循环双端链表

双链表:节点比单链表节点多一个prew值。可双向查找。

#Node节点,表示每一个元素
class Node(object):
    #定义节点,两个值:value,prew, next
    def __init__(self, value=None, prew=None, next=None):
        self.value,self.prew, self.next = value, prew, next
        
#循环双端链表
class CircualDoubleLinedList(object):
    #初始化
    def __init__(self, maxsize=None):
        self.maxsize = maxsize
        node = Node()
        node.next, node.prew = node. node
        self.root = node
        self.length = 0
    
    def __len__(self):
        return self.length
    
    def headnode(self):
        return self.root.next
    
    def tailnode(self):
        return self.root.prew
    
    #添加操作
    def append(self, value):
         #判断是否超过了最大值,若超过了,抛出异常
        if self.maxsize is not None and len(self) > self.maxsize:
            raise Exception('FUll')
        node = Node(value=value)
        tailnode = self.tailnode
        tailnode.next = node
        node.prew = tailnode
        node.next = self.root
        self.root.prew = node
        self.length += 1
    
    #左侧插入
    def appendleft(self, value):
        if self.maxsize is not None and len(self) > self.maxsize:
            raise Exception('FUll')
        node = Node(value = value)
        #如果节点为空
        if self.root.next is self.root:
            node.next = self.root
            node.prew = self.root
            self.root.next = node
            self.root.prew = node
        else:
            node.prew = self.root
            headnode = self.root.next
            node.next = headnode
            headnode.prew = node
            self.root.next = node
        self.length += 1
        
    #删除操作,O(1)
    def remove(self, node):
        if node is self.root:
            return
        else:
            node.prew.next = node.next
            node.next.prew = node.prew
        self.length -= 1
        return node
    
    #遍历
    def iter_node(self):
        if self.root.next is self.root:
            return
        curnode = self.root.next
        while curnode.next is not self.root:
            yield curnode
            curnode = curnode.next
        yield curnode
    
    #__iter__方法
    def __iter__(self):
        for node in self.iter_node():
            yield node.value
    
    #反向遍历
    def iter_node_reverse(self):
        if self.root.prew is self.root:
            return
        curnode = self.root.prew
        while curnode.prew is not self.root:
            yield curnode
            curnode = curnode.prew
        yield curnode

#测试
def test_double_link_list():
    dll = CircualDoubleLinedList()
    assert len(dll) == 0
    
    dll.appeend(0)
    dll.appeend(1)
    dll.appeend(2)
    
    assert list(dll) == [0, 1, 2]
    
    assert [node.value for node in dll.iter_node()] == [0, 1, 2]
    assert [node.value for node in dll.iter_node_reverse()] == [2, 1, 0]
    
    headnode = dll.headnode()
    assert headnode.value == 0
    
    dll.remove(headnode)
    assert len(dll) == 2
    assert [node.value for node in dll.iter_node()] == [1, 2]
    
    dll.appendleft(0)
    assert [node.value for node in dll.iter_node_reverse()] == [2, 1, 0]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值