python之数组,链表,栈,队列

1.数组

优点:

  • 索引操作速度快:通过索引可以直接访问元素,因此索引操作的时间复杂度是 $O(1)$,即常数级

缺点:

  • 插入、删除元素慢: 如果需要在中间或开始位置插入或删除元素,可能需要移动大量元素,因此这样的操作的时间复杂度是$O(n)$
  • 预先设置空间大小: 数组通常需要预先设置空间大小,这意味着在创建时需要估计数据的大小,并为其分配足够的内存空间。如果数组大小不够,可能需要重新分配内存并复制数据,这会带来额外的开销。如果数组太多,浪费空间

需要的参数:数组名称,大小,采用索引进行各种操作

2.链表

优点:

  • 不需要预先知道数据大小,实现灵活的内存动态管理
  • 插入、删除指定数据速度快

缺点:

  • 读取指定位置数据速度慢
  • 空间开销比较大

分类

单向链表

链表中最简单的一种是单向链表,它包含两个域,一个信息域和一个指针域。这个链接指向列表中的下一个节点,而最后一个节点则指向一个空值

需要的参数:节点的值,节点的后一个节点

循环链表(环形链表)

在一个循环链表中, 首节点和末节点被连接在一起,要遍历一个循环链表,可以开始于任意一个节点然后沿着列表的任一方向直到返回开始的节点

双向链表

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

需要的参数:节点的值,节点的前一个节点,节点的后一个节点

3.栈

特点:

  1. 先入后出,后入先出
  2. 除头尾节点之外,每个元素有一个前驱,一个后继

栈的结构是先进后出,类似于子弹的弹夹, 计算机结构如图:

4.队列

特点:

队列(queue)是一种遵循先入先出规则的线性数据结构,只允许在有序的线性结构集合的一端(队尾)进行加入数据(push)和 另一端(队首)移除数据(pop)的运算。

  1. 先入先出,后入后出
  2. 除头尾节点之外,每个元素有一个前驱,一个后继

5.双向对列

双向队列 ,就是在队列的基础上增加一个双端操作的功能。允许在头部和尾部执行元素的添加或删除操作

栈,队列,双向队列都可以用数组和链表表示

6.各种实现代码

6.1单链表

class ListNode:
    
    def __init__(self,val:int):
        self.val=val
        self.next=None
class MyLinkNode:
    def __init__(self):
        self.size=0
        self.head=ListNode(0)
    def add_index(self,val:int,index:int):
        if index>self.size:
            return -1
        index=max(0,index)
        add_node=ListNode(val)
        pre=self.head
        for _ in range(index):
            pre=pre.next
        add_node.next=pre.next
        pre.next=add_node
        self.size+=1
    def add_head(self,val:int):
        self.add_index(val,0)
    def add_tail(self,val:int):
        self.add_index(val,self.size)
    def get(self,index:int):
        if index<0 or index>=self.size:
            return -1
        pred=self.head
        for _ in range(index+1):
            pred=pred.next
        return pred.val
    def delete(self,index:int):
        if index<0 or index>=self.size:
            return -1
        pred=self.head
        for _ in range(index):
            pred=pred.next
        pred.next=pred.next.next
        self.size-=1
    def traverse(self):
        cur=self.head.next
        while cur:
            print(cur.val)
            cur=cur.next
if __name__=='__main__':
    link=MyLinkNode()
    link.add_tail(1)
    link.add_tail(2)
    link.add_tail(3)
    link.add_tail(4)
    link.add_index(8,2)
    link.delete(3)
    link.traverse()

6.2双向链表

class ListNode:
    def __init__(self,val):
        self.val=val
        self.next=None
        self.pre=None
class MyListNode:
    def __init__(self):
        self.head=ListNode(0)
        self.tail=ListNode(0)
        self.head.next=self.tail
        self.tail.pre=self.head
        self.size=0
    def add_index(self,index:int,val:int):
        if index>self.size:
            return -1
        else:
            if index<self.size-index:
                pred=self.head
                for _ in range(index):
                    pred=pred.next
                succ=pred.next
            else:
                succ=self.tail
                for _ in range(self.size-index):
                    succ=succ.pre
                pred=succ.pre
            add_node=ListNode(val)
            add_node.next=succ
            add_node.pre=pred
            pred.next=add_node
            succ.pre=add_node
            self.size+=1
    def add_head(self,val):
        self.add_index(0,val)
    def add_tail(self,val):
        self.add_index(self.size,val)
    def get(self,index):
        if index<0 or index>=self.size:
            return -1
        else:
            if index<self.size-index:
                cur=self.head
                for _ in range(index+1):
                    cur=cur.next
                return cur.val
            else:
                cur=self.tail
                for _ in range(self.size-index+1):
                    cur=cur.pre
                return cur.val
    def delete(self,index):
        if index<0 or index>=self.size:
            return -1
        else:
            if index<self.size-index:
                pred=self.head
                for _ in range(index):
                    pred=pred.next
                succ=pred.next.next
            else:
                succ=self.tail
                for _ in range(self.size-index-1):
                    succ=succ.pre
                pred=succ.pre.pre
            pred.next=succ
            succ.pre=pred
        self.size-=1
        
    def print_all(self):
        cur=self.head
        while cur:
            print(cur.val)
            cur=cur.next
if __name__=='__main__':
    link=MyListNode()
    link.add_tail(1)
    link.add_tail(2)
    link.add_tail(3)
    link.add_tail(4)
    link.add_tail(5)
    # link.delete(0)
    link.add_index(3,8)
    link.add_index(6,8)
    link.add_tail(11)
    link.add_head(20)
    link.print_all()

6.3循环链表

class ListNode:
    
    def __init__(self,val:int):
        self.val=val
        self.next=None
class MyLinkNode:
    def __init__(self):
        self.size=0
        self.head=ListNode(0)
        self.head.next=self.head
    def add_index(self,val:int,index:int):
        if index>self.size:
            return -1
        index=max(0,index)
        add_node=ListNode(val)
        pre=self.head
        for _ in range(index):
            pre=pre.next
        add_node.next=pre.next
        pre.next=add_node
        self.size+=1
    def add_head(self,val:int):
        self.add_index(val,0)
    def add_tail(self,val:int):
        self.add_index(val,self.size)
    def get(self,index:int):
        if index<0 or index>=self.size:
            return -1
        pred=self.head
        for _ in range(index+1):
            pred=pred.next
        return pred.val
    def delete(self,index:int):
        if index<0 or index>=self.size:
            return -1
        pred=self.head
        for _ in range(index):
            pred=pred.next
        pred.next=pred.next.next
        self.size-=1
    def traverse(self):
        cur=self.head.next
        count=1
        while cur:
            print(cur.val)
            cur=cur.next
            count+=1
            if count>self.size+3:
                break
if __name__=='__main__':
    link=MyLinkNode()
    link.add_tail(1)
    link.add_tail(2)
    link.add_tail(3)
    link.add_tail(4)
    link.traverse()

6.4栈——数组表示

class ArrayStack:
    def __init__(self):
        self.data:list[int]=[]
    def push(self,val):
        self.data.append(val)
    def pop(self):
        if self.is_empty():
            raise Exception('栈为空')
        else:
            return self.data.pop()
    def is_empty(self):
        return len(self.data)==0
    def top(self):
        if self.is_empty():
            raise Exception('栈为空')
        else:
            return(self.data[-1])
    def to_list(self):
        return self.data
if __name__=='__main__':
        stack=ArrayStack()
        stack.push(1)
        stack.push(2)
        stack.push(3)
        stack.push(4)
        print(stack.to_list())
        print(stack.top())
        stack.pop()
        print(stack.to_list())

6.5栈——链表表示

class ListNode:
  def __init__(self,val:int):
    self.val: int = val
    self.next = None


class LinkedListStack:
  def __init__(self):
    self.flag: ListNode|None = None
    self._size: int = 0


  def size(self) -> int:
    '''
     获取栈中元素的个数
     '''
    return self._size
  
  def is_empty(self) -> bool:
    '''
     判断栈是否为空
     '''
    return self._size == 0
  
  def push(self, val: int) -> None:
    '''
     入栈
     '''
    # 创建节点
    node = ListNode(val)
    # 将新节点的next指向原来的栈顶元素
    node.next = self.flag
    # 将栈顶指针指向新节点
    self.flag = node
    # 栈中元素个数+1
    self._size += 1
  def pop(self) -> int:
    '''
     出栈
     '''
    # 获取栈顶元素的值
    data = self.top()
    #  将栈顶指针指向栈顶元素的下一个元素
    self.flag = self.flag.next
    # 栈中元素个数-1
    self._size -= 1


    return data
  def top(self)-> int:
    '''
     获取栈顶元素
     '''
    if self.is_empty():
      raise Exception('Stack is empty')
    return self.flag.val
  def to_list(self):
    '''
     将栈转换为列表
     '''
    result = []
    # 获取栈顶元素
    node = self.flag
    # 判断栈顶元素是否为空
    while node:
      result.append(node.val)
      node = node.next
    return result


if __name__ =='__main__':
  stack = LinkedListStack()
  stack.push(1)
  stack.push(2)
  stack.push(3)


  print(stack.to_list())
  print(f'获取栈顶元素:{stack.top()}')
  print(stack.to_list())
  print(f'出栈:{stack.pop()}')
  print(f'栈的元素个数:{stack.size()}')
  print(f'栈是否为空:{stack.is_empty()}')

6.6队列——数组表示

class MyQueue:
  def __init__(self):
    self.items = []
  
  def push(self,val:int) ->None:
    '''
     入队
     '''
    self.items.append(val)


  def pop(self) ->int:
    '''
     出队
     '''
    return self.items.pop(0)
  
  def size(self) ->int:
    '''
     队列大小
     '''
    return len(self.items)
  
  def is_empty(self) ->bool:
    '''
     队列是否为空
     '''
    return self.size() == 0
  
  def peek(self) ->int:
    '''
     获取队首元素
     '''
    return self.items[0]
  
  def to_list(self) ->list:
    '''
     转换为列表
     '''
    return self.items




if __name__ == '__main__':
  queue = MyQueue()
  queue.push(1)
  queue.push(2)
  queue.push(3)
  print(f'转成列表后:{queue.to_list()}')
  print(f'出队:{queue.pop()}')
  print(f'转成列表后:{queue.to_list()}')
  print(f'访问队首元素:{queue.peek()}')
  print(f'转成列表后:{queue.to_list()}')
  print(f'队列是否为空:{queue.is_empty()}')
  print(f'队列是元素个数:{queue.size()}')

6.7队列——链表表示

class MyQueue:
  def __init__(self):
    self.items = []
  
  def push(self,val:int) ->None:
    '''
     入队
     '''
    self.items.append(val)


  def pop(self) ->int:
    '''
     出队
     '''
    return self.items.pop(0)
  
  def size(self) ->int:
    '''
     队列大小
     '''
    return len(self.items)
  
  def is_empty(self) ->bool:
    '''
     队列是否为空
     '''
    return self.size() == 0
  
  def peek(self) ->int:
    '''
     获取队首元素
     '''
    return self.items[0]
  
  def to_list(self) ->list:
    '''
     转换为列表
     '''
    return self.items




if __name__ == '__main__':
  queue = MyQueue()
  queue.push(1)
  queue.push(2)
  queue.push(3)
  print(f'转成列表后:{queue.to_list()}')
  print(f'出队:{queue.pop()}')
  print(f'转成列表后:{queue.to_list()}')
  print(f'访问队首元素:{queue.peek()}')
  print(f'转成列表后:{queue.to_list()}')
  print(f'队列是否为空:{queue.is_empty()}')
  print(f'队列是元素个数:{queue.size()}')

6.8双向队列-数组表示

class ArrayDeque:
  def __init__(self,capacity:int=8):
    self._data = [0] * capacity # 存储数据的数组
    self._head = 0       # 队头元素的下标
    self._size = 0       # 队列中元素的个数
  
  def capacity(self):
    '''返回队列的容量'''
    return len(self._data)
  
  def is_empty(self) -> bool:
    '''判断队列是否为空'''
    return self._size == 0
  
  def index(self,i:int) -> int:
    '''获取指定正确的索引'''
    return (i+self.capacity())%self.capacity()
  def peek_first(self) -> int:
    '''查看队头元素'''
    if self.is_empty():
      raise Exception("Deque is empty")
    return self._data[self._head]
  
  def peek_last(self) -> int:
    '''查看队尾元素'''
    if self.is_empty():
      raise Exception("Deque is empty")
    # 获取队尾元素的下标
    i = self.index(self._head + self._size - 1)
    return self._data[i]
  
  def push_last(self,val:int):
    '''增加队尾元素'''
    # 判断队列是否已满
    if self._size == self.capacity():
      raise Exception("Deque is full")
    # 获取队尾元素的下标
    i = self.index(self._head + self._size)
    # 将元素添加到队尾
    self._data[i] = val
    # 队列中元素的个数加1
    self._size += 1
  def push_first(self,val:int):
    '''增加队头元素'''
    # 判断队列是否已满
    if self._size == self.capacity():
      raise Exception("Deque is full")
    # 获取队头元素的下标
    i = self.index(self._head - 1)
    # 将元素添加到队头
    self._data[i] = val
    # 队列中元素的个数加1
    self._size += 1
    # 修改队头元素的下标
    self._head = i
  def pop_first(self) -> int:
    '''删除队头元素'''
    if self.is_empty():
      raise Exception("Deque is empty")
    # 获取队头元素的值
    val = self.peek_first()
    # 修改队头元素的下标
    self._head = self.index(self._head + 1)
    # 队列中元素的个数减1
    self._size -= 1
    return val
  def pop_last(self) -> int:
    '''删除队尾元素'''
    if self.is_empty():
      raise Exception("Deque is empty")
    # 获取队尾元素的值
    val = self.peek_last()
    # 队列中元素的个数减1
    self._size -= 1
    return val


  def to_list(self):
    '''转换为列表'''
    res = []
    for i in range(self._size):
      tmp_index = self.index(self._head + i)
      res.append(self._data[tmp_index])
    return res


if __name__ == "__main__":
  deque = ArrayDeque(5)
  deque.push_last(1)
  deque.push_last(2)
  deque.push_last(3)
  deque.push_last(4)
  deque.push_last(5)
  print(deque.to_list())   #  [1,2,3,4,5]
  deque.pop_first()      #  1
  deque.push_last(6)     #  [2,3,4,5,6]
  print(deque.to_list())   #  [2,3,4,5,6]
  print(f'队尾拿到数据:{deque.pop_last()}')  #  6
  deque.push_first(7)     # [7,2,3,4,5]
  print(deque.to_list())   # [7,2,3,4,5]

6.9双向队列-链表表示

class ArrayDeque:
  def __init__(self,capacity:int=8):
    self._data = [0] * capacity # 存储数据的数组
    self._head = 0       # 队头元素的下标
    self._size = 0       # 队列中元素的个数
  
  def capacity(self):
    '''返回队列的容量'''
    return len(self._data)
  
  def is_empty(self) -> bool:
    '''判断队列是否为空'''
    return self._size == 0
  
  def index(self,i:int) -> int:
    '''获取指定正确的索引'''
    return (i+self.capacity())%self.capacity()
  def peek_first(self) -> int:
    '''查看队头元素'''
    if self.is_empty():
      raise Exception("Deque is empty")
    return self._data[self._head]
  
  def peek_last(self) -> int:
    '''查看队尾元素'''
    if self.is_empty():
      raise Exception("Deque is empty")
    # 获取队尾元素的下标
    i = self.index(self._head + self._size - 1)
    return self._data[i]
  
  def push_last(self,val:int):
    '''增加队尾元素'''
    # 判断队列是否已满
    if self._size == self.capacity():
      raise Exception("Deque is full")
    # 获取队尾元素的下标
    i = self.index(self._head + self._size)
    # 将元素添加到队尾
    self._data[i] = val
    # 队列中元素的个数加1
    self._size += 1
  def push_first(self,val:int):
    '''增加队头元素'''
    # 判断队列是否已满
    if self._size == self.capacity():
      raise Exception("Deque is full")
    # 获取队头元素的下标
    i = self.index(self._head - 1)
    # 将元素添加到队头
    self._data[i] = val
    # 队列中元素的个数加1
    self._size += 1
    # 修改队头元素的下标
    self._head = i
  def pop_first(self) -> int:
    '''删除队头元素'''
    if self.is_empty():
      raise Exception("Deque is empty")
    # 获取队头元素的值
    val = self.peek_first()
    # 修改队头元素的下标
    self._head = self.index(self._head + 1)
    # 队列中元素的个数减1
    self._size -= 1
    return val
  def pop_last(self) -> int:
    '''删除队尾元素'''
    if self.is_empty():
      raise Exception("Deque is empty")
    # 获取队尾元素的值
    val = self.peek_last()
    # 队列中元素的个数减1
    self._size -= 1
    return val


  def to_list(self):
    '''转换为列表'''
    res = []
    for i in range(self._size):
      tmp_index = self.index(self._head + i)
      res.append(self._data[tmp_index])
    return res


if __name__ == "__main__":
  deque = ArrayDeque(5)
  deque.push_last(1)
  deque.push_last(2)
  deque.push_last(3)
  deque.push_last(4)
  deque.push_last(5)
  print(deque.to_list())   #  [1,2,3,4,5]
  deque.pop_first()      #  1
  deque.push_last(6)     #  [2,3,4,5,6]
  print(deque.to_list())   #  [2,3,4,5,6]
  print(f'队尾拿到数据:{deque.pop_last()}')  #  6
  deque.push_first(7)     # [7,2,3,4,5]
  print(deque.to_list())   # [7,2,3,4,5]

  • 26
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值