zoukankan      html  css  js  c++  java
  • 单双链表

    集合中存储的元素是有顺序的。顺序表的结构可以分为两种形式:单数据类型和多数据类型。

      单数据类型:例如np.array

      单数据类型:内存连续开辟,在内存中存储 int a = 10,20,30图例如下

      

      多数据类型:例如python中的list

      多数据类型:内存非连续开辟,在内存中如何存储 li = 10,'a',96.5,如何获取每一个数据值呢?

      

       - 顺序表的弊端:顺序表的结构需要预先知道数据大小来申请连续的存储空间,而在进行增加删除时又需要进行数据的搬迁。

       - Python中的 list 和 tuple 两种类型采用了顺序表的实现技术。

    三、链表

      相对于顺序表,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。

      链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是不像顺序表一样连续存储数据,而是每一个结点(数据存储单元)里存放下一个结点的信息(即地址):

      

    四、单向链表:

      单向链表也叫单链表,是表中最简单的一种形式,它的每个节点包含两个域,一个信息域(元素域)和一个链接域。这个链接指向链表中的下一个节点,而最后一个节点的链接域则指向一个空值。

        - 表中元素elem用来存放具体的数据。

        - 链接域next用来存放下一个节点的位置。

        - 变量p指向链表的头节点(首节点)的位置,从p出发能找到表中的任意节点。

      单向链表的抽象数据类型定义:

        . is_empty():链表是否为空

        . length():链表长度

        . travel():遍历整个链表

        . add(item):链表头部添加元素

        . append(item):链表尾部添加元素

        . insert(pos, item):指定位置添加元素

        . remove(item):删除节点

        . search(item):查找节点是否存在

    复制代码
    # 第一步:创建节点(node)
    class Node(object):
        def __init__(self,item):
            # 存放新节点的值
            self.item = item
            # 新节点没有下一个链接地址
            self.next = None
    
    # 创建链接
    class Link(object):
        def __init__(self):
            # _head永远指向的第一个节点的地址
            self._head = None
            
        # 添加一个链接
        def add(self,item):
            # 创建新节点
            node = Node(item)
            # 将新节点的next地址指向 旧节点的_head指向
            node.next = self._head
            # 新节点地址指向新节点内存空间地址
            self._head = node
            
        # 获取链表值
        def travel(self):
            # 获取第一个节点指针
            cur = self._head
            
            # 判断链表next指向为空时,则为链表的最后一个节点
            while cur:
                # 打印节点item属性值
                print(cur.item)
                # 将新的节点指针赋值给cur变量
                cur = cur.next
                
        def length(self):
            # 获取第一个节点指针
            cur = self._head
            # 长度计数器
            count = 0
            
            # 判断链表next指向为空时,则为链表的最后一个节点
            while cur:
                # 打印节点item属性值
                count += 1
                # 将新的节点指针赋值给cur变量
                cur = cur.next
                
            # 打印计数器
            print("当前链表长度: ",count)
            return count
            
    
    
        # 判断链表是否为空
        def isEmpty(self):
            # 判断链表指针为None时,链表为空,返回True
            return self._head == None
    
        
        # 链表尾部追加元素
        def append(self,item):
            node = Node(item)
    
            # 判断链表是否为空
            if self.isEmpty():
                # 链表为空,添加新节点
                self._head = node
                return
    
            # 链表不为空,追加节点
            cur = self._head
            # 定义一个变量,保存前一个节点的地址
            pre = None
    
            # 判断
            while cur:
                pre = cur
                cur = cur.next
    
            # 最后next指针指向新加节点
            pre.next = node
    
        # 查询链表 查询成功返回True,否则返回False
        def search(self,item):
            find = False
            cur = self._head
    
            while cur:
                # 查询成功
                if cur.item == item:
                    find = True
                    break
                else:
                    # 链表指针指向下一个链表节点
                    cur = cur.next
    
            return find
    
        # 链表的插入操作
        def insert(self,pos,item):
            # 查询链表长度
            length = self.length()
            if pos <=0 or pos >length:
                print("插入位置超出范围!!!")
                return
    
            # pos添加的位置规定从1开始
            node = Node(item)
            cur = self._head
            pre = None
            
            # 在位置1插入
            if pos == 1:
                node.next = self._head
                self._head = node
                return 
    
            # for循环,使链表指针指向pos插入位置
            for i in range(1,pos):
                pre = cur
                cur = cur.next
    
            # 此时链表指针指向需要插入数据的位置
            # 此时把pre指向的上一个指针地址指向插入节点的地址
            pre.next = node
            # 把插入节点地址指针指向下一个节点地址
            node.next = cur
    
        # 删除指定位置节点
        def remove(self,item):
            # 获取第一个节点指针
            cur = self._head
            pre = None
    
            # 此处没有节点可以删除
            if self._head == None:
                return
    
            # 删除第一个节点
            if cur.item == item:
                self._head = cur.next
                return
    
            # 删除其他位置节点
            while cur:
                # 将新的节点指针赋值给下一个节点地址
                if cur.item == item:
                    pre.next = cur.next
                    break
                else:
                    pre = cur
                    cur = cur.next
    
    
    # 链表测试 # 实例化链表对象 link = Link() # 添加节点 link.add(1) link.add(2) link.add(3) # 显示链表值 link.travel() # 删除元素2 link.remove(2) link.travel() # 插入在链表位置1处插入一个节点6 link.insert(4,8) link.travel()
    复制代码

    五、单向循环链表

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

      基本操作和单链表基本一样,实现代码如下:

    复制代码
    # coding=utf-8
    # 单向循环链表
    
    
    class Node:
        """节点"""
        def __init__(self, item):
            self.item = item
            self.next = None
    
        def __str__(self):
            return str(self.item)
    
    
    class SinCycLinkedList:
        """单向循环链表"""
        def __init__(self):
            self._head = None
    
        def is_empty(self):
            """判断链表是否为空"""
            return self._head is None
    
        def length(self):
            """链表长度"""
            if self.is_empty():
                return 0
            count = 1
            cur = self._head
            while cur.next != self._head:
                # print("cur", cur.item)
                count += 1
                cur = cur.next
            return count
    
        def travel(self):
            """遍历"""
            if self.is_empty():
                return
    
            cur = self._head
            print(cur.item)
            while cur.next != self._head:
                cur = cur.next
                print(cur.item)
    
        def add(self, item):
            """在头部添加一个节点"""
            node = Node(item)
            if self.is_empty():
                self._head = node
                node.next = self._head
            else:
                node.next = self._head
                cur = self._head
                while cur.next != self._head:
                    cur = cur.next
    
                cur.next = node
                self._head = node
    
        def append(self, item):
            """在尾部添加一个节点"""
            node = Node(item)
            if self.is_empty():
                self._head = node
                node.next = self._head
            else:
                cur = self._head
                # print(type(cur), cur.item, cur.next)
                while cur.next != self._head:
                    cur = cur.next
    
                # print(cur.item)
                cur.next = node
                node.next = self._head
    
        def insert(self, pos, item):
            """指定位置pos添加节点"""
            if pos <= 0:
                self.add(item)
            elif pos > (self.length() - 1):
                self.append(item)
            else:
                node = Node(item)
                cur = self._head
                cur_pos = 0
                while cur.next != self._head:
                    if (pos - 1) == cur_pos:
                        node.next = cur.next
                        cur.next = node
                        break
                    cur_pos += 1
                    cur = cur.next
    
        def remove(self, item):
            """删除一个节点"""
            if self.is_empty():
                return
    
            pre = self._head
            # 删除首节点
            if pre.item == item:
                cur = pre
                while cur.next != self._head:
                    cur = cur.next
    
                cur.next = pre.next     # 删除首节点(跳过该节点)
                self._head = pre.next   # 重新指定首节点
    
            # 删除其他的节点
            else:
                cur = pre
                while cur.next != self._head:
                    if cur.next.item == item:
                        cur.next = cur.next.next
                    cur = cur.next
    
        def search(self, item):
            """查找节点是否存在"""
            if self.is_empty():
                return -1
    
            cur_pos = 0
            cur = self._head
            if cur.item == item:
                return cur_pos
    
            while cur.next != self._head:
                if cur.item == item:
                    return cur_pos
                cur_pos += 1
                cur = cur.next
    
            if cur_pos == self.length() - 1:
                return -1
    
    
    if __name__ == "__main__":
        ll = SinCycLinkedList()
        ll.add(1)       # 1
        ll.add(2)       # 2 1
        # ll.travel()
        ll.append(3)    # 2 1 3
        ll.insert(2, 4) # 2 1 4 3
        ll.insert(4, 5) # 2 1 4 3 5
        ll.insert(0, 6) # 6 2 1 4 3 5
        print("length:", ll.length())        # 6
        ll.travel()                           # 6 2 1 4 3 5
        print("search(3)", ll.search(3))     # 4
        print("search(7)", ll.search(7))     # -1
        print("search(6)", ll.search(6))    # 0
        print("remove(1)")
        ll.remove(1)
        print("length:", ll.length())       # 6 2 4 3 5
        print("remove(6)")
        ll.remove(6)
        ll.travel()
    复制代码

    六、双向链表

      一种更复杂的链表是 "双向链表" 或 "双面链表"。每个节点有两个链接:一个指向前一个节点,当次节点为第一个节点时,指向空值;而另一个指向下一个节点,当此节点为最后一个节点时,指向空值。

      

      代码实现:

    复制代码
    # coding=utf-8
    # 双向链表
    
    
    class Node:
        """节点"""
        def __init__(self, item):
            self.item = item
            self.prev = None
            self.next = None
    
    
    class DLinkList:
        """双向链表"""
        def __init__(self):
            self._head = None
    
        def is_empty(self):
            """判断链表是否为空"""
            return self._head is None
    
        def length(self):
            """获取链表长度"""
            if self.is_empty():
                return 0
            else:
                cur = self._head
                count = 1
                while cur.next is not None:
                    count += 1
                    cur = cur.next
    
                return count
    
        def travel(self):
            """遍历链表"""
            print("↓↓" * 10)
            if self.is_empty():
                print("")
    
            else:
                cur = self._head
                print(cur.item)
                while cur.next is not None:
                    cur = cur.next
                    print(cur.item)
            print("↑↑" * 10)
    
        def add(self, item):
            """链表头部添加节点"""
            node = Node(item)
            if self.is_empty():
                self._head = node
            else:
                cur = self._head
    
                node.next = cur
                cur.prev = node
                self._head = node
    
        def append(self, item):
            """链表尾部添加节点"""
            node = Node(item)
            if self.is_empty():
                self._head = node
            else:
                cur = self._head
                # 遍历找到最后一个节点
                while cur.next is not None:
                    cur = cur.next
    
                # 在尾节点添加新的节点
                cur.next = node
                node.prev = cur
    
        def insert(self, pos, item):
            """指定位置添加"""
            # 头部添加
            if pos <= 0:
                self.add(item)
    
            # 尾部添加
            elif pos > (self.length() - 1):
                self.append(item)
    
            # 其他位置添加
            else:
                node = Node(item)
    
                cur = self._head
                cur_pos = 0
                while cur.next is not None:
                    if cur_pos == (pos - 1):
                        # 与下一个节点互相指向
                        node.next = cur.next
                        cur.next.prev = node
                        # 与上一个节点互相指向
                        cur.next = node
                        node.prev = cur
                    cur_pos += 1
                    cur = cur.next
    
        def remove(self, item):
            """删除节点"""
            if self.is_empty():
                return
            else:
                cur = self._head
                # 删除首节点
                if cur.item == item:
                    self._head = cur.next
                    cur.next.prev = None
    
                # 删除其他节点
                else:
                    while cur.next is not None:
                        if cur.item == item:
                            # 删除之前:1 ←→ [2] ←→ 3
                            # 删除之后:1 ←→ 3
                            cur.prev.next = cur.next
                            cur.next.prev = cur.prev
                        cur = cur.next
    
                    # 删除尾节点
                    if cur.item == item:
                        cur.prev.next = None
    
    
        def search(self, item):
            """查找节点是否存在"""
            if self.is_empty():
                return -1
            else:
                cur = self._head
                cur_pos = 0
                while cur.next is not None:
                    if cur.item == item:
                        return cur_pos
    
                    cur_pos += 1
                    cur = cur.next
    
                if cur_pos == (self.length() - 1):
                    return -1
    
    
    if __name__ == "__main__":
        ll = DLinkList()
        ll.add(1)       # 1
        ll.add(2)       # 2 1
        ll.append(3)    # 2 1 3
        ll.insert(2, 4) # 2 1 4 3
        ll.insert(4, 5) # 2 1 4 3 5
        ll.insert(0, 6) # 6 2 1 4 3 5
        print("length:", ll.length())   # 6
        ll.travel()                 # 6 2 1 4 3 5
        print("search(3)", ll.search(3))
        print("search(4)", ll.search(4))
        print("search(10)", ll.search(10))
        ll.remove(1)
        print("length:", ll.length())
        ll.travel()
        print("删除首节点 remove(6):")
        ll.remove(6)
        ll.travel()
        print("删除尾节点 remove(5):")
        ll.remove(5)
        ll.travel()
  • 相关阅读:
    如何编写优雅的代码:05. 设计模式(下)
    ArcGIS之Cartogram地图变形记
    GIS规划应用——基于哈夫模型的GIS服务区分析
    基于GIS的旅游辐射区人口统计
    图斑整理之字段计算器使用技巧
    ArcGIS制作放射状流向地图(Radial Flow Map)
    SQL Server时间粒度系列
    (原)SQL Server 代理作业执行持续时间简述
    (原)SQL Server 系统提供功能的三个疑惑
    sql server实现自定义分割月功能
  • 原文地址:https://www.cnblogs.com/anthony-wang0228/p/11524705.html
Copyright © 2011-2022 走看看