前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >打牢地基-链表

打牢地基-链表

作者头像
用户1081422
发布2020-04-08 10:19:31
3010
发布2020-04-08 10:19:31
举报
文章被收录于专栏:T客来了

章节

  • 动态数组 & 栈 & 队列 与 链表的不同
  • 链表特性 & 图示
  • 链表实现 & 各操作时间复杂度分析

动态数组 & 栈 & 队列 与 链表的不同

重要 动态数组、栈、队列 底层依托的都是静态数组 链表是天然的动态数据结构

链表重要性 & 简介 & 图示

重要性:

  1. 1. 真正的动态数据结构
  2. 2. 最简单的动态数据结构
  3. 3. 涉及更深入的引用(或者指针)
  4. 4. 更深入的理解递归 (天然具有递归属性,node.next is node )
  5. 5. 辅助组成其他数据结构 - 栈、队列也可以用链表实现,还有hashmap

链表 - LinkedList

  1. 1. 数据存储在节点中
  2. class Node {
  3. // 存储具体的数据
  4. E e;
  5. // 指向下一个node的引用
  6. Node next;
  7. }

链表数据结构如下图所示:

优点: 1.真正的动态,不需要处理固定容量问题 2.增删数据非常方便

缺点:

  1. 丧失了随机访问的缺点

链表实现 & 各操作时间复杂度分析

链表实现 - python 版

注意: 关键点: 找到要插入节点的前一个节点 LinkedList - (head实现)

代码语言:javascript
复制
#!/usr/bin/env python
 
# -*- coding: utf-8 -*-
 
"""
 
# @Time    : 2020/2/5 下午3:44
 
# @Author  : bofengliu@tencent.com
 
# @Site    : 
 
# @File    : LinkedList.py
 
# @Software: PyCharm
 
# 自己实现链表元素需要的节点
 
# head 版
 
"""
  
class Node:
 
 def __init__(self, e=None, next=None):
 
        self.e = e
 
        self.next = next
 


 
 def to_string(self):
 
 return self.e
 

 
class LinkedList:
 
 """
 
    链表中的成员变量,head 指向链表中头节点,size 是链表中元素的个数
 
    """
 
 
 def __init__(self):
 
        self._head = None
 
        self._size = 0
 
 
 def get_size(self):
 
 return self._size
 

 def is_empty(self):
 
 return self._size == 0
 
 
 def add_first(self, val):
 
 """
 
        头插法
 
        :param node:
 
        :return:
 
        """
 
        node = Node(e=val)
 
        node.next = self._head
 
        self._head = node
 
 # 简写
 
 # self._head = Node(val, self._head)
 
        self._size += 1
 


 
 def add(self, index, e):
 
 if index < 0 or index > self._size:
 
 raise (Exception, 'Add failed! Illegal index')
 
 if index == 0:
 
 # 这步操作可以通过虚拟头节点屏蔽掉
 
            self.add_first(e)
 
 else:
 
            prev = self._head
 
 for i in range(0, index - 1):
 
                prev = prev.next
 
            new_node = Node(e=e)
 
            new_node.next = prev.next
 
            prev.next = new_node
 
 # 简写
 
            prev.next = Node(e, prev.next)
 
        self._size += 1
 


 
 def add_last(self, e):
 
        self.add(self._size, e)
 

LinkedList - (dummy_head 虚拟节点实现)

代码语言:javascript
复制
#!/usr/bin/env python 
# -*- coding: utf-8 -*- 
""" 
# @Time    : 2020/2/5 下午3:44 
# @Author  : bofengliu@tencent.com 
# @Site    :  
# @File    : LinkedList.py 
# @Software: PyCharm 
# 自己实现链表元素需要的节点 
# dummy_head(虚拟头节点)版 
# 删除和新增都需要找到前一个节点 
""" 
class Node: 
 def __init__(self, e=None, next=None): 
        self.e = e 
        self.next = next 
 def to_string(self): 
 return self.e 
class LinkedList: 
 """ 
    链表中的成员变量,head 指向链表中头节点,size 是链表中元素的个数 
    """ 
 def __init__(self): 
        self._dummy_head = Node(None, None) 
        self._size = 0 
 def get_size(self): 
 return self._size 
 def is_empty(self): 
 return self._size == 0 
 def add(self, index, e): 
 """ 
        实质是占用原有index元素的位置,并将原有index元素向后移动 
        :param index: 
        :param e: 
        :return: 
        """ 
 if index < 0 or index > self._size: 
 raise (Exception, 'Add failed! Illegal index') 
        prev = self._dummy_head 
 for i in range(0, index): 
            prev = prev.next 
        new_node = Node(e=e) 
        new_node.next = prev.next 
        prev.next = new_node 
 # 简写 
 # prev.next = Node(e, prev.next) 
        self._size += 1 
 def add_first(self, e): 
 """ 
        头插法 
        :param e: 
        :return: 
        """ 
        self.add(0, e) 
 def add_last(self, e): 
        self.add(self._size, e) 
 def get(self, index): 
 if index < 0 or index > self._size: 
 raise (Exception, 'Get failed! Illegal index') 
 # 链表的真实头节点 
        cur = self._dummy_head.next 
 for i in range(0, index): 
            cur = cur.next 
 return cur.e 
 def get_first(self): 
 return self.get(0) 
 def get_last(self): 
 return self.get(self._size - 1) 
 # 更新操作 
 def set(self, index, e): 
 if index < 0 or index > self._size: 
 raise (Exception, 'set failed! Illegal index') 
        cur = self._dummy_head.next 
 for i in range(0, index): 
            cur = cur.next 
        cur.e = e 
 # 删除操作 
 def remove(self, index): 
 if index < 0 or index > self._size: 
 raise (Exception, 'set failed! Illegal index') 
        prev = self._dummy_head 
 for i in range(0, index): 
            prev = prev.next 
        del_node = prev.next 
        prev.next = del_node.next 
        del_node.next = None 
        self._size -= 1 
 return del_node.e 
 def remove_first(self): 
 return self.remove(0) 
 def remove_last(self): 
 return self.remove(self._size - 1) 
 # 查找链表中是否存在某个元素 
 def contains(self, e): 
        cur = self._dummy_head.next 
 while cur is not None: 
 if cur.e == e: 
 return True 
            cur = cur.next 
 return False 
 def to_string(self): 
        res_linkedlist_arr = [] 
        res_linkedlist_arr.append('LinkedList:size = %d  ' % self._size) 
        cur = self._dummy_head.next 
 while cur is not None: 
            val = cur.e 
 if isinstance(val, int): 
                val = str(val) 
            res_linkedlist_arr.append(val + ' -> ') 
            cur = cur.next 
        res_linkedlist_arr.append(' NULL ') 
 return "".join(res_linkedlist_arr) 
if __name__ == '__main__': 
    a = 1 
    linkedList = LinkedList() 
 for i in range(0, 5): 
        linkedList.add_first(i) 
 print(linkedList.to_string()) 
    linkedList.set(1, 2) 
 print(linkedList.to_string()) 
    linkedList.add(5, 10) 
 print(linkedList.to_string()) 
    linkedList.remove_first() 
 print(linkedList.to_string()) 
    linkedList.remove_last() 
 print(linkedList.to_string()) 
    linkedList.remove(1) 
 print(linkedList.to_string()
 

各操作时间复杂度分析

add 操作
代码语言:javascript
复制
add_last  O(n) 复杂度
 
add_first O(1) 复杂度
 
add(index, e) O(n/2) 即 O(n) 的复杂度
 
remove 操作
代码语言:javascript
复制
remove_last O(n)
 
remove_first O(1)
 
remove(index,e) O(n/2) 即 O(n) 的复杂度
 
set 操作
代码语言:javascript
复制
set(index,e)  O(n) 

get

代码语言:javascript
复制
get(index) O(n)
 
contains(e) O(n)

增删改查的时间复杂度都是O(n) 级别的,单对链表头节点(即虚拟头节点的下一个实体节点),时间复杂度是O(1)

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-02-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 T客来了 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 章节
  • 动态数组 & 栈 & 队列 与 链表的不同
  • 链表重要性 & 简介 & 图示
    • 重要性:
    • 链表 - LinkedList
    • 链表实现 & 各操作时间复杂度分析
      • 链表实现 - python 版
        • 各操作时间复杂度分析
          • add 操作
          • remove 操作
          • set 操作
        • get
        相关产品与服务
        数据保险箱
        数据保险箱(Cloud Data Coffer Service,CDCS)为您提供更高安全系数的企业核心数据存储服务。您可以通过自定义过期天数的方法删除数据,避免误删带来的损害,还可以将数据跨地域存储,防止一些不可抗因素导致的数据丢失。数据保险箱支持通过控制台、API 等多样化方式快速简单接入,实现海量数据的存储管理。您可以使用数据保险箱对文件数据进行上传、下载,最终实现数据的安全存储和提取。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档