• Python 单向链表、双向链表


    用面向对象实现Linkedlist链表

    单向链表实现append、iternodes

    双向链表实现append、pop、insert、remove、iternodes

    单向链表与双向链表

    单向链表:

    就好比小朋友在操场上,手拉着手。

    分为数据域和指针域,指针域指向下一个数据,代码中分别用val 和next 表示。

    整个链表用一个容器来存储,因为单向链表的数据虽然真正在内存中是散落的,但是某种关系可以把这些数据有序的组织起来,所以最合适的数据结构应该是列表。列表存储还支持追加和索引,容器在代码中用self.nodes=[] 表示。

    如图:内存中的数据散落存储,5表示头head,9表示tail尾。

    在链表为空时,需要定义头和尾,来表示前一个数据和下一个数据,头和尾在代码中用head 和tail 分别表示,前一个数据和下一个数据用prev 和next 分别表示。

    0)链表数据为空时,顺序是:head --> tail,头和尾都可以用None表示;

    1)链表中有一个数据时,顺序就变成了:  head--> 数据1 -->tail;

    2)链表有两个数据时,顺序变成了:head -->数据1 -->数据2 -->tail;

    3)链表有三个数据时,顺序变成了:head -->数据1 -->数据2 -->数据3 -->tail

    以此类推。。。

    代码:

    class SingleNode:
        """代表一个节点"""
    
        def __init__(self, val, next=None, prev=None):
            self.val = val
            self.next = next
            self.prev = prev
    
        def __repr__(self):
            return str(self.val)
    
        def __str__(self):
            return str(self.val)
    
    
    class LinkedList:
        """容器类,某种方式存储一个个节点"""
    
        def __init__(self):
            self.nodes = []
            # 不需要插入的列表来说,检索方便,但是insert、remove不合适
            self.head = None
            self.tail = None
    
        def __len__(self):
            return len(self.nodes)
    
        def __getitem__(self, item):
            return self.nodes[item]
    
        def append(self, val):
            node = SingleNode(val)  # 实例化的一个新节点
            prev = self.tail
            if prev is None:
                self.head = node
            else:
                prev.next = node
            self.nodes.append(val)
            self.tail = node
    
        def iternodes(self, reverse=False):
            current = self.head
            while current:
                yield current
                current = current.next
    
    
    ll = LinkedList()
    ll.append(5)
    ll.append(7)
    
    for node in ll.iternodes():
        print(node)
    
    print(ll[0])
    print(ll[1])
    

      

      

    双向链表:

    0) append 尾部追加

    1) pop 尾部弹出

    2) insert 头部插入、中间插入、尾部插入

    3) remove 头部删除、中间删除、尾部删除

    class SingleNode:
        def __init__(self,val,next=None,prev=None):
            self.val = val
            self.next = next
            self.prev = prev
    
        def __repr__(self):
            return str(self.val)
    
        def __str__(self):
            return str(self.val)
    
    
    class LinkedList:
        def __init__(self):
            # self.nodes = []
            self.head = None
            self.tail = None
    
        def append(self,val):
            node = SingleNode(val)
            # prev = self.tail
            # if prev is None:
            if self.head is None: #only one
                self.head = node
            else: # >1
                self.tail.next = node
                node.prev = self.tail
            # self.nodes.append(node)
            self.tail = node
    
        def iternodes(self,reverse=False):
            current = self.tail if reverse else self.head
            while current:
                yield current
                current = current.prev if reverse else current.next
    
        def pop(self):
            if self.tail is None:  #0个数据
                raise Exception('Empty')
            tail = self.tail
            prev = tail.prev
            # next = tail.next #尾的下一个恒定为None
            if prev is None:  # =0, =1
                self.head = None
                self.tail = None
            else:  # >1
                self.tail = prev
                prev.next = None
            return tail.val
    
        def getitem(self,index):  #index不考虑传入str类型,全当做int类型
            if index < 0:
                return None
            current = None
            for i,node in enumerate(self.iternodes()):
                if i == index:
                    current = node
                    break
            if current is not None:
                return current
    
        def insert(self,index,val):
            if index < 0:   #不考虑负索引
                raise Exception('Error')
            current = None
            for i, node in enumerate(self.iternodes()):
                if i == index:
                    current = node
                    break
            if current is None: #考虑元素为空、为一个
                self.append(val)
                return
            #尾部、头部、中间追加
            prev = current.prev
            next = current.next
    
            node = SingleNode(val)
            if prev is None: #头部插入
                self.head = node
                # node.next = current
                # current.prev = node
            else:
                node.prev = prev
                # node.next = current  #和前面条件共同部分抽出来放后面
                # current.prev = node
                prev.next = node
            node.next = current
            current.prev = node
    
        def remove(self,index):
            if self.tail is None:
                raise Exception('Empty')
            if index < 0:
                raise ValueError('Wrong Index {}'.format(index))
    
            current = None
            for i,node in enumerate(self.iternodes()):
                if i == index:
                    current = node
                    break
            if current is None: #Not found
                raise ValueError('Wrong Index {}. Out of boundary'.format(index))
    
            prev = current.prev
            next = current.next
    
            if prev is None and next is None: #only one node
                self.head = None
                self.tail = None
            elif prev is None: #删头部
                self.head = next
                next.prev = None
            elif next is None: #删尾部
                self.tail = prev
                prev.next = None
            else:  #中间
                prev.next = next
                next.prev = prev
    
            del current
    
    
        # def __getitem__(self, item):
        #     return self.nodes[item]
    
    
    ll = LinkedList()
    ll.append('abc')
    ll.append(1)
    ll.append(2)
    ll.append(3)
    ll.append(4)
    ll.append(5)
    ll.append('def')
    
    ll.insert(6,6)  #边界
    ll.insert(7,7)   #尾部
    ll.insert(8,8)  #尾部
    ll.insert(0,123)  #头部
    ll.insert(100,100)  #超界
    
    # ll.remove(100)
    
    # ll.pop()
    # ll.pop()
    
    for node in ll.iternodes(False): #False
        print(node)
    print('~'*30)
    # print(ll[0])
    # print(ll[1])
    ll.remove(5)
    ll.remove(6)
    ll.remove(0)
    ll.remove(1)
    for node in ll.iternodes(False): #False
        print(node)
    

      

      

  • 相关阅读:
    boost.property_tree的高级用法(你们没见过的操作)
    MFC- OnIdle空闲处理
    华为代码质量军规 (1) 数组访问,必须进行越界保护
    WinSocket 编程
    【C/C++】链表的理解与使用
    单链表
    C++ lambda表达式 (二)
    C++ lambda表达式 (一)
    C++11 volatile 类型
    关于结构体内存对齐方式的总结(#pragma pack()和alignas())
  • 原文地址:https://www.cnblogs.com/i-honey/p/7833358.html
Copyright © 2020-2023  润新知