使用python实现数组、链表、队列、栈的方法


Posted in Python onDecember 20, 2019

引言

什么是数据结构?

  • 数据结构是指相互之间存在着一种或多种关系的数据元素的集合和该集合中数据元素之间的关系组成。
  • 简单来说,数据结构就是设计数据以何种方式组织并存储在计算机中。
  • 比如:列表,集合和字典等都是数据结构
  • N.Wirth:“程序=数据结构+算法”

数据结构按照其逻辑结构可分为线性结构、树结构、图结构

  • 线性结构:数据结构中的元素存在一对一的互相关系。
  • 树结构:数据结构中的元素存在一对多的互相关系。
  • 图结构:数据结构中的元素存在多对多的互相关系。

数组

在python中是没有数组的,有的是列表,它是一种基本的数据结构类型。

实现

class Array(object):
 def __init__(self, size=32):
  """
  :param size: 长度
  """
  self._size = size
  self._items = [None] * size

 # 在执行array[key]时执行
 def __getitem__(self, index):
  return self._items[index]

 # 在执行array[key] = value 时执行
 def __setitem__(self, index, value):
  self._items[index] = value

 # 在执行len(array) 时执行
 def __len__(self):
  return self._size
 
 # 清空数组
 def clear(self, value=None):
  for i in range(len(self._items)):
   self._items[i] = value

 # 在遍历时执行
 def __iter__(self):
  for item in self._items:
   yield item

使用

a = Array(4)
a[0] = 1
print(a[0]) # 1

a.clear() 
print(a[0]) # None

a[0] = 1
a[1] = 2
a[3] = 4
for i in a:
 print(i) # 1, 2, None, 4

链表

链表中每一个元素都是一个对象,每一个对象被称为节点,包含有数据域value和指向下一个节点的指针next。

通过各个节点直接的相互链接,最终串成一个链表。

使用python实现数组、链表、队列、栈的方法

实现

class Node(object):
 def __init__(self, value=None, next=None):
  self.value, self.next = value, next

class LinkedList(object):
 def __init__(self, size=None):
  """
  :param size: int or None, 如果None,则该链表可以无限扩充
  """
  self.size = size
  # 定义一个根节点
  self.root = Node()
  # 尾节点始终指向最后一个节点
  self.tail_node = None
  self.length = 0
 def __len__(self):
  return self.length
 def append(self, value):
  # size 不为 None, 且长度大于等于size则链表已满
  if self.size and len(self) >= self.size:
   raise Exception("LinkedList is full")
  # 构建节点
  node = Node(value)
  tail_node = self.tail_node
  # 判断尾节点是否为空
  if tail_node is None:
   # 还没有 append 过,length = 0, 追加到 root 后
   self.root.next = node
  else:
   # 否则追加到最后一个节点的后边,并更新最后一个节点是 append 的节点
   tail_node.next = node
  # 把尾节点指向node
  self.tail_node = node
  # 长度加一
  self.length += 1
 # 往左边添加
 def append_left(self, value):
  if self.size and len(self) >= self.size:
   raise Exception("LinkedList is full")
  # 构建节点
  node = Node(value)
  # 链表为空,则直接添加设置
  if self.tail_node is None:
   self.tail_node = node
  # 设置头节点为根节点的下一个节点
  head_node = self.root.next
  # 把根节点的下一个节点指向node
  self.root.next = node
  # 把node的下一个节点指向原头节点
  node.next = head_node
  # 长度加一
  self.length += 1
 # 遍历节点
 def iter_node(self):
  # 第一个节点
  current_node = self.root.next
  # 不是尾节点就一直遍历
  while current_node is not self.tail_node:
   yield current_node
   # 移动到下一个节点
   current_node = current_node.next
  # 尾节点
  if current_node is not None:
   yield current_node
 # 实现遍历方法
 def __iter__(self):
  for node in self.iter_node():
   yield node.value
 # 删除指定元素
 def remove(self, value):
  # 删除一个值为value的节点,只要使该节点的前一个节点的next指向该节点的下一个
  # 定义上一个节点
  perv_node = self.root
  # 遍历链表
  for current_node in self.iter_node():
   if current_node.value == value:
    # 把上一个节点的next指向当前节点的下一个节点
    perv_node.next = current_node.next
    # 判断当前节点是否是尾节点
    if current_node is self.tail_node:
     # 更新尾节点 tail_node
     # 如果第一个节点就找到了,把尾节点设为空
     if perv_node is self.root:
      self.tail_node = None
     else:
      self.tail_node = perv_node
    # 删除节点,长度减一,删除成功返回1
    del current_node
    self.length -= 1
    return 1
   else:
    perv_node = current_node
  # 没找到返回-1
  return -1
 # 查找元素,找到返回下标,没找到返回-1
 def find(self, value):
  index = 0
  # 遍历链表,找到返回index,没找到返回-1
  for node in self.iter_node():
   if node.value == value:
    return index
   index += 1
  return -1
 # 删除第一个节点
 def popleft(self):
  # 链表为空
  if self.root.next is None:
   raise Exception("pop from empty LinkedList")
  # 找到第一个节点
  head_node = self.root.next
  # 把根节点的下一个节点,指向第一个节点的下一个节点
  self.root.next = head_node.next
  # 获取删除节点的value
  value = head_node.value
  # 如果第一个节点是尾节点, 则把尾节点设为None
  if head_node is self.tail_node:
   self.tail_node = None
  # 长度减一,删除节点,返回该节点的值
  self.length -= 1
  del head_node
  return value
 # 清空链表
 def clear(self):
  for node in self.iter_node():
   del node
  self.root.next = None
  self.tail_node = None
  self.length = 0
 # 反转链表
 def reverse(self):
  # 第一个节点为当前节点,并把尾节点指向当前节点
  current_node = self.root.next
  self.tail_node = current_node
  perv_node = None
  while current_node:
   # 下一个节点
   next_node = current_node.next
   # 当前节点的下一个节点指向perv_node
   current_node.next = perv_node
   # 当前节点的下一个节点为空,则把根节点的next指向当前节点
   if next_node is None:
    self.root.next = current_node
   # 把当前节点赋值给perv_node
   perv_node = current_node
   # 把下一个节点赋值为当前节点
   current_node = next_node

使用

ll = LinkedList()

ll.append(0)
ll.append(1)
ll.append(2)
ll.append(3)
print(len(ll)) # 4
print(ll.find(2)) # 2
print(ll.find(-1)) # -1

ll.clear()
print(len(ll)) # 0
print(list(ll)) # []

循环链表

双链表中每一个节点有两个指针,一个指向后面节点、一个指向前面节点。

使用python实现数组、链表、队列、栈的方法

循环链表实现

class Node(object):
 def __init__(self, value=None, prev=None, next=None):
  self.value = value
  self.prev = prev
  self.next = next


class CircularDoubleLinkedList(object):
 """
 双向循环链表
 """

 def __init__(self, maxsize=None):
  self.maxsize = maxsize
  node = Node()
  node.prev = node
  node.next = node
  self.root = node
  self.length = 0

 def __len__(self):
  return self.length

 def head_node(self):
  return self.root.next

 def tail_node(self):
  return self.root.prev

 # 遍历
 def iter_node(self):
  if self.root.next is self.root:
   return
  current_node = self.root.next
  while current_node.next is not self.root:
   yield current_node
   current_node = current_node.next
  yield current_node

 def __iter__(self):
  for node in self.iter_node():
   yield node.value

 # 反序遍历
 def iter_node_reverse(self):
  if self.root.prev is self.root:
   return
  current_node = self.root.prev
  while current_node.prev is not self.root:
   yield current_node
   current_node = current_node.prev
  yield current_node

 def append(self, value):
  if self.maxsize is not None and len(self) >= self.maxsize:
   raise Exception("LinkedList is full")
  node = Node(value)
  tail_node = self.tail_node() or self.root
  tail_node.next = node
  node.prev = tail_node
  node.next = self.root
  self.root.prev = node
  self.length += 1

 def append_left(self, value):
  if self.maxsize is not None and len(self) >= self.maxsize:
   raise Exception("LinkedList is full")
  node = Node(value)
  if self.root.next is self.root:
   self.root.next = node
   node.prev = self.root
   node.next = self.root
   self.root.prev = node
  else:
   node.next = self.root.next
   self.root.next.prev = node
   self.root.next = node
   node.prev = self.root
  self.length += 1

 def remove(self, node):
  if node is self.root:
   return
  node.next.prev = node.prev
  node.prev.next = node.next
  self.length -= 1
  return node

循环链表的使用

dll = CircularDoubleLinkedList()

dll.append(0)
dll.append(1)
dll.append(2)

assert list(dll) == [0, 1, 2]
print(list(dll)) # [0, 1, 2]

print([node.value for node in dll.iter_node()]) # [0, 1, 2]
print([node.value for node in dll.iter_node_reverse()]) # [2, 1, 0]

headnode = dll.head_node()
print(headnode.value) # 0
dll.remove(headnode)
print(len(dll)) # 2

队列

队列(Queue)是一个数据集合,仅允许在列表的一端进行插入,另一端进行删除。

进行插入的一端成为队尾(rear),插入动作称为进队或入队。

进行删除的一端称为队头(front),删除动作称为出队。

队列的性质:先进先出(First-in, First-out)。

使用python实现数组、链表、队列、栈的方法

基于数组实现环形队列

class Array(object):
 def __init__(self, size=32):
  """
  :param size: 长度
  """
  self._size = size
  self._items = [None] * size

 # 在执行array[key]时执行
 def __getitem__(self, index):
  return self._items[index]

 # 在执行array[key] = value 时执行
 def __setitem__(self, index, value):
  self._items[index] = value

 # 在执行len(array) 时执行
 def __len__(self):
  return self._size
 
 # 清空数组
 def clear(self, value=None):
  for i in range(len(self._items)):
   self._items[i] = value

 # 在遍历时执行
 def __iter__(self):
  for item in self._items:
   yield item


class ArrayQueue(object):
 def __init__(self, maxsize):
  self.maxsize = maxsize
  self.array = Array(maxsize)
  self.head = 0
  self.tail = 0

 def __len__(self):
  return self.head - self.tail

 # 入队
 def push(self, value):
  if len(self) >= self.maxsize:
   raise Exception("Queue is full")
  self.array[self.head % self.maxsize] = value
  self.head += 1

 # 出队
 def pop(self):
  value = self.array[self.tail % self.maxsize]
  self.tail += 1
  return value

使用

size = 5
q = ArrayQueue(size)
for i in range(size):
 q.push(i)

print(len(q)) # 5

print(q.pop()) # 0
print(q.pop()) # 1

基于双向链表实现双向队列

class Node(object):
 def __init__(self, value=None, prev=None, next=None):
  self.value = value
  self.prev = prev
  self.next = next


class CircularDoubleLinkedList(object):
 """
 双向循环链表
 """

 def __init__(self, maxsize=None):
  self.maxsize = maxsize
  node = Node()
  node.prev = node
  node.next = node
  self.root = node
  self.length = 0

 def __len__(self):
  return self.length

 def head_node(self):
  return self.root.next

 def tail_node(self):
  return self.root.prev

 # 遍历
 def iter_node(self):
  if self.root.next is self.root:
   return
  current_node = self.root.next
  while current_node.next is not self.root:
   yield current_node
   current_node = current_node.next
  yield current_node

 def __iter__(self):
  for node in self.iter_node():
   yield node.value

 # 反序遍历
 def iter_node_reverse(self):
  if self.root.prev is self.root:
   return
  current_node = self.root.prev
  while current_node.prev is not self.root:
   yield current_node
   current_node = current_node.prev
  yield current_node

 def append(self, value):
  if self.maxsize is not None and len(self) >= self.maxsize:
   raise Exception("LinkedList is full")
  node = Node(value)
  tail_node = self.tail_node() or self.root
  tail_node.next = node
  node.prev = tail_node
  node.next = self.root
  self.root.prev = node
  self.length += 1

 def append_left(self, value):
  if self.maxsize is not None and len(self) >= self.maxsize:
   raise Exception("LinkedList is full")
  node = Node(value)
  if self.root.next is self.root:
   self.root.next = node
   node.prev = self.root
   node.next = self.root
   self.root.prev = node
  else:
   node.next = self.root.next
   self.root.next.prev = node
   self.root.next = node
   node.prev = self.root
  self.length += 1

 def remove(self, node):
  if node is self.root:
   return
  node.next.prev = node.prev
  node.prev.next = node.next
  self.length -= 1
  return node


# 双向队列
class Deque(CircularDoubleLinkedList):
 # 从右边出队
 def pop(self):
  if len(self) <= 0:
   raise Exception("stark is empty!")
  tail_node = self.tail_node()
  value = tail_node.value
  self.remove(tail_node)
  return value

 # 从左边出队
 def popleft(self):
  if len(self) <= 0:
   raise Exception("stark is empty!")
  head_node = self.head_node()
  value = head_node.value
  self.remove(head_node)
  return value

双向队列

两端都可以进行插入,删除。

使用python实现数组、链表、队列、栈的方法

基于双向链表实现双向队列

class Node(object):
 def __init__(self, value=None, prev=None, next=None):
  self.value = value
  self.prev = prev
  self.next = next


class CircularDoubleLinkedList(object):
 """
 双向循环链表
 """

 def __init__(self, maxsize=None):
  self.maxsize = maxsize
  node = Node()
  node.prev = node
  node.next = node
  self.root = node
  self.length = 0

 def __len__(self):
  return self.length

 def head_node(self):
  return self.root.next

 def tail_node(self):
  return self.root.prev

 # 遍历
 def iter_node(self):
  if self.root.next is self.root:
   return
  current_node = self.root.next
  while current_node.next is not self.root:
   yield current_node
   current_node = current_node.next
  yield current_node

 def __iter__(self):
  for node in self.iter_node():
   yield node.value

 # 反序遍历
 def iter_node_reverse(self):
  if self.root.prev is self.root:
   return
  current_node = self.root.prev
  while current_node.prev is not self.root:
   yield current_node
   current_node = current_node.prev
  yield current_node

 def append(self, value):
  if self.maxsize is not None and len(self) >= self.maxsize:
   raise Exception("LinkedList is full")
  node = Node(value)
  tail_node = self.tail_node() or self.root
  tail_node.next = node
  node.prev = tail_node
  node.next = self.root
  self.root.prev = node
  self.length += 1

 def append_left(self, value):
  if self.maxsize is not None and len(self) >= self.maxsize:
   raise Exception("LinkedList is full")
  node = Node(value)
  if self.root.next is self.root:
   self.root.next = node
   node.prev = self.root
   node.next = self.root
   self.root.prev = node
  else:
   node.next = self.root.next
   self.root.next.prev = node
   self.root.next = node
   node.prev = self.root
  self.length += 1

 def remove(self, node):
  if node is self.root:
   return
  node.next.prev = node.prev
  node.prev.next = node.next
  self.length -= 1
  return node


# 双向队列
class Deque(CircularDoubleLinkedList):
 # 从右边出队
 def pop(self):
  if len(self) <= 0:
   raise Exception("stark is empty!")
  tail_node = self.tail_node()
  value = tail_node.value
  self.remove(tail_node)
  return value

 # 从左边出队
 def popleft(self):
  if len(self) <= 0:
   raise Exception("stark is empty!")
  head_node = self.head_node()
  value = head_node.value
  self.remove(head_node)
  return value

双向队列的使用

dq = Deque()
dq.append(1)
dq.append(2)
print(list(dq)) # [1, 2]

dq.appendleft(0)
print(list(dq)) # [0, 1, 2]

dq.pop()
print(list(dq)) # [0, 1]

dq.popleft()
print(list(dq)) # [1]

dq.pop()
print(len(dq)) # 0

 

栈(Stack)是一个数据集合,可以理解为只能在一端插入或删除操作的链表。

栈的特点:后进先出(Last-in, First-out)

栈的概念:

  • 栈顶
  • 栈底

栈的基本操作:

  • 进栈(压栈):push
  • 出栈:pop

使用python实现数组、链表、队列、栈的方法

基于双向队列实现

class Node(object):
 def __init__(self, value=None, prev=None, next=None):
  self.value = value
  self.prev = prev
  self.next = next


class CircularDoubleLinkedList(object):
 """
 双向循环链表
 """
 def __init__(self, maxsize=None):
  self.maxsize = maxsize
  node = Node()
  node.prev = node
  node.next = node
  self.root = node
  self.length = 0

 def __len__(self):
  return self.length

 def head_node(self):
  return self.root.next

 def tail_node(self):
  return self.root.prev

 # 遍历
 def iter_node(self):
  if self.root.next is self.root:
   return
  current_node = self.root.next
  while current_node.next is not self.root:
   yield current_node
   current_node = current_node.next
  yield current_node

 def __iter__(self):
  for node in self.iter_node():
   yield node.value

 # 反序遍历
 def iter_node_reverse(self):
  if self.root.prev is self.root:
   return
  current_node = self.root.prev
  while current_node.prev is not self.root:
   yield current_node
   current_node = current_node.prev
  yield current_node

 def append(self, value):
  if self.maxsize is not None and len(self) >= self.maxsize:
   raise Exception("LinkedList is full")
  node = Node(value)
  tail_node = self.tail_node() or self.root
  tail_node.next = node
  node.prev = tail_node
  node.next = self.root
  self.root.prev = node
  self.length += 1

 def append_left(self, value):
  if self.maxsize is not None and len(self) >= self.maxsize:
   raise Exception("LinkedList is full")
  node = Node(value)
  if self.root.next is self.root:
   self.root.next = node
   node.prev = self.root
   node.next = self.root
   self.root.prev = node
  else:
   node.next = self.root.next
   self.root.next.prev = node
   self.root.next = node
   node.prev = self.root
  self.length += 1

 def remove(self, node):
  if node is self.root:
   return
  node.next.prev = node.prev
  node.prev.next = node.next
  self.length -= 1
  return node


class Deque(CircularDoubleLinkedList):
 def pop(self):
  if len(self) <= 0:
   raise Exception("stark is empty!")
  tail_node = self.tail_node()
  value = tail_node.value
  self.remove(tail_node)
  return value

 def popleft(self):
  if len(self) <= 0:
   raise Exception("stark is empty!")
  head_node = self.head_node()
  value = head_node.value
  self.remove(head_node)
  return value


class Stack(object):
 def __init__(self):
  self.deque = Deque() 
 
 # 压栈
 def push(self, value):
  self.deque.append(value)

 # 出栈
 def pop(self):
  return self.deque.pop()

使用

s = Stack()
s.push(0)
s.push(1)
s.push(2)

print(s.pop()) # 2
print(s.pop()) # 1
print(s.pop()) # 0

 总结

以上所述是小编给大家介绍的使用python实现数组、链表、队列、栈的方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Python 相关文章推荐
Python实现的Google IP 可用性检测脚本
Apr 23 Python
python根据京东商品url获取产品价格
Aug 09 Python
详解 Python 与文件对象共事的实例
Sep 11 Python
python实现mysql的读写分离及负载均衡
Feb 04 Python
Python中文件的读取和写入操作
Apr 27 Python
python多任务之协程的使用详解
Aug 26 Python
python GUI库图形界面开发之PyQt5窗口布局控件QStackedWidget详细使用方法
Feb 27 Python
python实现图片,视频人脸识别(dlib版)
Nov 18 Python
在终端启动Python时报错的解决方案
Nov 20 Python
python 列表推导和生成器表达式的使用
Feb 01 Python
pandas按条件筛选数据的实现
Feb 20 Python
Python实现查询剪贴板自动匹配信息的思路详解
Jul 09 Python
python隐藏类中属性的3种实现方法
Dec 19 #Python
Python合并2个字典成1个新字典的方法(9种)
Dec 19 #Python
关于Python中定制类的比较运算实例
Dec 19 #Python
在python中利用try..except来代替if..else的用法
Dec 19 #Python
Python字符串的修改方法实例
Dec 19 #Python
python中property和setter装饰器用法
Dec 19 #Python
python装饰器代替set get方法实例
Dec 19 #Python
You might like
使用PHP批量生成随机用户名
2008/07/10 PHP
无需数据库在线投票调查php代码
2016/07/20 PHP
Thinkphp5.0框架视图view的循环标签用法示例
2019/10/12 PHP
PHP实现常用排序算法的方法
2020/02/05 PHP
javascript 全角转换实现代码
2009/07/17 Javascript
jquery easyui的tabs使用时的问题
2010/03/23 Javascript
JavaScript中的prototype使用说明
2010/04/13 Javascript
在HTML代码中使用JavaScript代码的例子
2014/10/16 Javascript
jquery增加和删除元素的方法
2015/01/14 Javascript
使用AngularJS 应用访问 Android 手机的图片库
2015/03/24 Javascript
深入学习JavaScript中的原型prototype
2015/08/13 Javascript
jquery验证邮箱格式并显示提交按钮
2015/11/07 Javascript
JS提交form表单实例分析
2015/12/10 Javascript
jQuery绑定事件on()与弹窗的简要概述
2016/04/27 Javascript
jquery实现下拉菜单的手风琴效果
2017/07/23 jQuery
vue.js评论发布信息可插入QQ表情功能
2017/08/08 Javascript
vue中遇到的坑之变化检测问题(数组相关)
2017/10/13 Javascript
jquery实现点击a链接,跳转之后,该a链接处显示背景色的方法
2018/01/18 jQuery
JS加密插件CryptoJS实现的DES加密示例
2018/08/16 Javascript
Vue常用指令详解分析
2018/08/19 Javascript
[00:33]2016完美“圣”典风云人物:BurNIng宣传片
2016/12/10 DOTA
理解Python中的类与实例
2015/04/27 Python
Python使用tablib生成excel文件的简单实现方法
2016/03/16 Python
python3新特性函数注释Function Annotations用法分析
2016/07/28 Python
Python合并字典键值并去除重复元素的实例
2016/12/18 Python
使用Python对SQLite数据库操作
2017/04/06 Python
pycharm中连接mysql数据库的步骤详解
2017/05/02 Python
Python升级导致yum、pip报错的解决方法
2017/09/06 Python
python实现的自动发送消息功能详解
2019/08/15 Python
CSS3实现复选框动画特效示例代码
2016/09/27 HTML / CSS
公司财务总监岗位职责
2013/12/14 职场文书
财务总经理岗位职责
2014/02/16 职场文书
2014年生产管理工作总结
2014/12/23 职场文书
课文《燕子》教学反思
2016/02/17 职场文书
Linux中Nginx的防盗链和优化的实现代码
2021/06/20 Servers
python文件与路径操作神器 pathlib
2022/04/01 Python