数据结构与算法之《链表结构》

链表

  1. 定义
    线性表的一种,不像顺序表连续存储数据,而是在每一个数据存储单元(节点)中存放下一数据单元的位置信息(地址)。如下图在这里插入图片描述

  2. 特点
    充分利用计算机的内存空间,实现灵活的动态内存管理,但数据操作相对于顺序表的连续存储效率较低。

  3. 单向链表
    单向链表,也叫单链表,每个节点包含两个域,一个是元素域用于存放数据元素,一个是链接域用于链接下一节点,最后一个节点的链接域指向空值。请看下图:
    在这里插入图片描述
    图中elem表示元素域,next表示链接域,p表示链表的头结点位置,由p出发才能找到表中的任意节点
    在这里插入图片描述

#-----------------------单链表python实现-------------------#
class Node(object):
    """节点"""
    def __init__(self,data):
        self.data = data    # 元素区
        self.next = None    # 链接区

class SingleLinkList(object):
    """单链表"""
    def __init__(self,data=None):
        node = None
        if data:
            node = Node(data)
        self.__head = node

    def is_empty(self):         #时间复杂度:O(1)
        """链表判空"""
        return self.__head == None
        
    def lenth(self):            #时间复杂度:O(n)
        """链表长度"""
        cur_node = self.__head  # 游标节点
        count = 0   # 计数
        while cur_node != None:
            count += 1
            cur_node = cur_node.next
        return count
    def __len__(self):
        """链表长度"""
        return self.lenth()

    def travel(self):           #时间复杂度:O(n)
        """遍历"""
        print("SingleLinkList:[",end="")
        cur_node = self.__head
        while cur_node != None:
            if cur_node.next == None:
                print(cur_node.data,end="")
                break
            print(cur_node.data,end=", ")
            cur_node = cur_node.next
        print("]") 

    def add(self,data):         #时间复杂度:O(1)
        """在头部添加元素"""
        new_node = Node(data)
        new_node.next = self.__head
        self.__head = new_node
    
    def append(self,data):      #时间复杂度:O(n)
        """在末尾添加元素"""
        new_node = Node(data)
        if self.is_empty():
            self.__head = new_node
        else:
            cur_node = self.__head
            while cur_node.next != None:
                cur_node = cur_node.next
            cur_node.next = new_node
            
    def insert(self,pos,data):  #时间复杂度:O(n)
        """在指定位置添加节点"""
        new_node = Node(data)
        # pos <=0 在头结点处插入
        if pos <= 0:
            self.add(data)
        # pos > len()-1 在尾结点插入
        elif pos > self.lenth()-1:
            self.append(data)
        else:
            pre_node = None         # 前节点游标
            cur_node = self.__head  # 节点游标
            count = 0
            while count <= pos-1:
                count += 1
                pre_node = cur_node
                cur_node = cur_node.next
            new_node.next = cur_node
            pre_node.next = new_node
        return data        
        
    def remove(self,data):      #时间复杂度:O(n)
        """删除指定元素"""
        pre_node = None
        cur_node = self.__head
        while cur_node != None:
            if cur_node.data == data:
                if cur_node == self.__head:
                    self.__head = cur_node.next
                    return data
                pre_node.next = cur_node.next
                return data
            pre_node = cur_node
            cur_node = cur_node.next
        return None
    
    def search(self,data):      #时间复杂度:O(n)
        """查找元素"""
        cur_node = self.__head
        pos = 0
        while cur_node != None:
            if cur_node.data == data:
                return pos
            cur_node = cur_node.next
            pos += 1
        return None

    def clear(self):            #时间复杂度:O(1)
        """清空链表"""
        self.__head = None	# 清除头节点后其他节点可由python垃圾回收机制自动回收
        
    def pop(self):              #时间复杂度:O(n)
        """弹出尾部元素"""
        if self.is_empty():
            return None
        pre_node = None
        cur_node = self.__head
        if cur_node.next == None:
            self.__head = None
        else:
            while cur_node.next != None:
                pre_node = cur_node
                cur_node = cur_node.next
            pre_node.next = None
        return cur_node.data
#---------------------------------------------------------#
  1. 双向链表
    每个节点有两个链接,一个指向前一个节点,当此节点为第一个节点时,指向空值;一个指向下一个节点,当此节点为最后一个节点时,指向空值。如下图所示:
    在这里插入图片描述
    图中head表示头节点地址,0表示指向空
    在这里插入图片描述
#----------------------双向链表python实现----------------------------#
from SingleLinkList import SingleLinkList

class Node(object):
    """双向链表节点"""
    def __init__(self,data):
        self.data = data
        self.prev = None
        self.next = None

class DoubleLinkList(SingleLinkList):
    """双向链表"""
    def __init__(self,data=None):
        super().__init__(data)

    # 继承单链表的判空
    # 继承单链表的长度
    # 继承单链表的遍历
    
    def add(self,data):         #时间复杂度:O(1)
        """在头部添加元素"""
        new_node = Node(data)
        if self.is_empty():
            self._SingleLinkList__head = new_node
        else:
            new_node.next = self._SingleLinkList__head
            self._SingleLinkList__head.prev = new_node
            self._SingleLinkList__head = new_node

    def append(self,data):      #时间复杂度:O(n)
        """在末尾添加元素"""
        new_node = Node(data)
        if self.is_empty():
            self._SingleLinkList__head = new_node
        else:
            cur_node = self._SingleLinkList__head
            while cur_node.next != None:
                cur_node = cur_node.next
            new_node.prev = cur_node
            cur_node.next = new_node

    def insert(self,pos,data):  #时间复杂度:O(n)
        """在指定位置添加节点"""
        new_node = Node(data)
        # pos <=0 在头结点处插入
        if pos <= 0:
            self.add(data)
        # pos > len()-1 在尾结点插入
        elif pos > self.lenth()-1:
            self.append(data)
        else:
            cur_node = self._SingleLinkList__head  # 节点游标
            count = 0
            while count <= pos-1:
                count += 1
                cur_node = cur_node.next
            new_node.prev = cur_node.prev
            new_node.next = cur_node
            cur_node.prev = new_node
            new_node.prev.next = new_node
        return data

    def remove(self,data):      #时间复杂度:O(n)
        """删除指定元素"""
        cur_node = self._SingleLinkList__head
        while cur_node != None:
            if cur_node.data == data:
                if cur_node == self._SingleLinkList__head:
                    self._SingleLinkList__head = cur_node.next
                    if cur_node.next:
                        cur_node.next.prev = None
                    return data
                cur_node.prev.next = cur_node.next
                if cur_node.next:
                    cur_node.next.prev = cur_node.prev
                return data
            cur_node = cur_node.next
        return None

    def search(self,data):      #时间复杂度:O(n)
        """查找元素"""
        cur_node = self._SingleLinkList__head
        pos = 0
        while cur_node != None:
            if cur_node.data == data:
                return pos
            cur_node = cur_node.next
            pos += 1
        return None

    def pop(self):              #时间复杂度:O(n)
        """弹出尾部元素"""
        cur_node = self._SingleLinkList__head
        if self.is_empty():
            return None
        if cur_node.next == None:
            self._SingleLinkList__head = None
        else:
            while cur_node.next != None:
                cur_node = cur_node.next
            cur_node.prev.next = None
        return cur_node.data
#-------------------------------------------------------------------#
  1. 单向循环链表
    单向循环链表是单链表的一个变形,链表中最后一个节点的链接域不再指向空,而是指向头结点。如图所示:
    在这里插入图片描述
    图中p表示头结点地址,指向头节点
  2. 链表与顺序表对比
    链表失去了顺序表的随机读取优点,同时增加了节点链接域,空间开销较大,但对存储空间使用相对灵活。链表与顺序表各操作复杂度比较:
操作链表顺序表
元素访问O(n)O(1)
在头部插入/删除O(1)O(n)
在尾部插入/删除O(n)O(1)
在中间插入/删除O(n)O(n)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值