Python实战开发及案例分析(32)—— 柔性数组

        柔性数组(Dynamic Array)是一种能够在运行时动态调整大小的数据结构,常用于实现类似于Python列表(list)那样的可变数组。在实现动态数组时,我们通常使用倍增策略,即当数组容量不足时,将其容量加倍。

实现柔性数组

        为了实现一个简单的柔性数组,我们可以遵循以下步骤:

  1. 初始化数组:创建一个固定容量的初始数组。
  2. 添加元素:在数组末尾添加新元素,如果数组已满,则扩展其容量。
  3. 扩展数组:当数组容量不足时,创建一个新的更大的数组,并将旧数组的元素复制到新数组中。
  4. 其他操作:实现其他常用的数组操作,如删除元素、获取元素等。

Python实现柔性数组

        下面是一个使用Python实现柔性数组的示例:

class DynamicArray:def __init__(self):self.capacity = 1  # 初始容量self.size = 0      # 当前元素数量self.array = self._make_array(self.capacity)def _make_array(self, capacity):"""创建一个新的空数组"""return [None] * capacitydef _resize(self, new_capacity):"""将数组的容量调整为 new_capacity"""new_array = self._make_array(new_capacity)for i in range(self.size):new_array[i] = self.array[i]self.array = new_arrayself.capacity = new_capacitydef append(self, element):"""在数组末尾添加新元素"""if self.size == self.capacity:self._resize(2 * self.capacity)  # 扩展数组容量self.array[self.size] = elementself.size += 1def delete(self):"""删除数组末尾的元素"""if self.size == 0:raise IndexError("delete from empty array")self.array[self.size - 1] = Noneself.size -= 1if 0 < self.size < self.capacity // 4:self._resize(self.capacity // 2)  # 缩小数组容量def get(self, index):"""获取索引处的元素"""if not 0 <= index < self.size:raise IndexError("index out of bounds")return self.array[index]def __len__(self):"""返回数组中元素的数量"""return self.sizedef __str__(self):"""返回数组的字符串表示"""return str([self.array[i] for i in range(self.size)])# 测试柔性数组
dynamic_array = DynamicArray()
print("Initial array:", dynamic_array)# 添加元素
dynamic_array.append(1)
dynamic_array.append(2)
dynamic_array.append(3)
print("Array after appending 1, 2, 3:", dynamic_array)# 获取元素
print("Element at index 1:", dynamic_array.get(1))# 删除元素
dynamic_array.delete()
print("Array after deleting last element:", dynamic_array)# 继续添加元素
dynamic_array.append(4)
dynamic_array.append(5)
dynamic_array.append(6)
print("Array after appending 4, 5, 6:", dynamic_array)

案例分析:实现一个栈(Stack)

        使用柔性数组,我们可以实现一个简单的栈(Stack)数据结构。栈是一种后进先出(LIFO)的数据结构,具有压栈(push)、弹栈(pop)和查看栈顶元素(peek)等操作。

实现栈
class Stack:def __init__(self):self.dynamic_array = DynamicArray()def push(self, element):"""压栈"""self.dynamic_array.append(element)def pop(self):"""弹栈"""if len(self.dynamic_array) == 0:raise IndexError("pop from empty stack")element = self.dynamic_array.get(len(self.dynamic_array) - 1)self.dynamic_array.delete()return elementdef peek(self):"""查看栈顶元素"""if len(self.dynamic_array) == 0:raise IndexError("peek from empty stack")return self.dynamic_array.get(len(self.dynamic_array) - 1)def is_empty(self):"""检查栈是否为空"""return len(self.dynamic_array) == 0def __len__(self):"""返回栈中元素的数量"""return len(self.dynamic_array)def __str__(self):"""返回栈的字符串表示"""return str(self.dynamic_array)# 测试栈
stack = Stack()
print("Initial stack:", stack)# 压栈
stack.push(10)
stack.push(20)
stack.push(30)
print("Stack after pushing 10, 20, 30:", stack)# 查看栈顶元素
print("Top element:", stack.peek())# 弹栈
print("Popped element:", stack.pop())
print("Stack after popping:", stack)# 检查栈是否为空
print("Is stack empty?", stack.is_empty())

总结

        柔性数组是一种重要的数据结构,能够在运行时动态调整大小,适用于实现类似Python列表那样的可变数组。通过倍增策略和动态扩展容量,柔性数组在需要频繁添加和删除元素的场景中表现出色。我们还展示了如何使用柔性数组实现栈数据结构,并通过实例代码演示了其基本操作。柔性数组和栈的数据结构在实际应用中广泛存在,例如内存管理、任务调度等领域。

更复杂的应用与优化

        在继续探讨柔性数组的应用时,我们可以进一步扩展和优化其实现,并探讨其他数据结构的实现,如队列(Queue)和双端队列(Deque)。我们还可以讨论如何提高柔性数组的性能,以及在实际应用中的优化策略。

队列(Queue)的实现

        队列是一种先进先出(FIFO)的数据结构,具有入队(enqueue)和出队(dequeue)操作。使用柔性数组实现队列需要处理好元素的移动和容量管理。

实现队列
class Queue:def __init__(self):self.dynamic_array = DynamicArray()def enqueue(self, element):"""入队"""self.dynamic_array.append(element)def dequeue(self):"""出队"""if len(self.dynamic_array) == 0:raise IndexError("dequeue from empty queue")element = self.dynamic_array.get(0)for i in range(1, len(self.dynamic_array)):self.dynamic_array.array[i - 1] = self.dynamic_array.array[i]self.dynamic_array.delete()return elementdef is_empty(self):"""检查队列是否为空"""return len(self.dynamic_array) == 0def __len__(self):"""返回队列中元素的数量"""return len(self.dynamic_array)def __str__(self):"""返回队列的字符串表示"""return str(self.dynamic_array)# 测试队列
queue = Queue()
print("Initial queue:", queue)# 入队
queue.enqueue(10)
queue.enqueue(20)
queue.enqueue(30)
print("Queue after enqueue 10, 20, 30:", queue)# 出队
print("Dequeued element:", queue.dequeue())
print("Queue after dequeue:", queue)# 检查队列是否为空
print("Is queue empty?", queue.is_empty())

双端队列(Deque)的实现

        双端队列(Deque)是一种允许在两端进行添加和删除操作的数据结构。使用柔性数组实现双端队列需要处理好两端的操作和容量管理。

实现双端队列
class Deque:def __init__(self):self.dynamic_array = DynamicArray()def add_front(self, element):"""从队列头部添加元素"""if self.dynamic_array.size == self.dynamic_array.capacity:self.dynamic_array._resize(2 * self.dynamic_array.capacity)for i in range(self.dynamic_array.size, 0, -1):self.dynamic_array.array[i] = self.dynamic_array.array[i - 1]self.dynamic_array.array[0] = elementself.dynamic_array.size += 1def add_rear(self, element):"""从队列尾部添加元素"""self.dynamic_array.append(element)def remove_front(self):"""从队列头部移除元素"""if len(self.dynamic_array) == 0:raise IndexError("remove from empty deque")element = self.dynamic_array.get(0)for i in range(1, len(self.dynamic_array)):self.dynamic_array.array[i - 1] = self.dynamic_array.array[i]self.dynamic_array.delete()return elementdef remove_rear(self):"""从队列尾部移除元素"""return self.dynamic_array.delete()def is_empty(self):"""检查队列是否为空"""return len(self.dynamic_array) == 0def __len__(self):"""返回队列中元素的数量"""return len(self.dynamic_array)def __str__(self):"""返回队列的字符串表示"""return str(self.dynamic_array)# 测试双端队列
deque = Deque()
print("Initial deque:", deque)# 从尾部添加元素
deque.add_rear(10)
deque.add_rear(20)
deque.add_rear(30)
print("Deque after adding 10, 20, 30 at rear:", deque)# 从头部添加元素
deque.add_front(40)
deque.add_front(50)
print("Deque after adding 40, 50 at front:", deque)# 从头部移除元素
print("Removed element from front:", deque.remove_front())
print("Deque after removing element from front:", deque)# 从尾部移除元素
print("Removed element from rear:", deque.remove_rear())
print("Deque after removing element from rear:", deque)# 检查双端队列是否为空
print("Is deque empty?", deque.is_empty())

优化策略

        在实际应用中,为了提高柔性数组的性能,我们可以采取一些优化策略:

  1. 减少内存复制:在扩展数组容量时,可以采用更高的倍增系数,如 1.5 倍,而不是 2 倍,以减少内存复制的频率。
  2. 惰性缩减:在缩小数组容量时,可以采用惰性缩减策略,即只有当数组容量利用率低于某个阈值时才进行缩减,以避免频繁的内存操作。
  3. 预分配内存:在初始化时,根据预估的数据量预先分配足够的内存,以减少后续的扩展操作。
  4. 双指针技术:在实现双端队列时,可以使用双指针(头指针和尾指针)来分别管理两端的操作,以提高效率。

总结

        通过深入研究柔性数组的实现及其在不同数据结构(如队列和双端队列)中的应用,我们可以更好地理解动态数组的灵活性和高效性。在实际应用中,通过优化策略和合理的设计,柔性数组可以在处理大量数据时表现出色。继续探索和优化这些数据结构,将为我们在解决复杂问题时提供更多有效的工具和方法。

更复杂的柔性数组优化与应用

        在进一步探讨柔性数组的优化和应用时,我们可以结合更多的实际场景和需求来提升其性能和功能。以下内容将介绍一些高级优化技术和更复杂的应用,包括动态内存管理、多线程环境下的并发处理,以及结合算法和数据结构实现实际应用。

高级优化技术

1. 动态内存管理

        动态内存管理是优化柔性数组性能的关键,通过合理的内存分配和释放策略,可以有效减少内存碎片,提高内存利用率。

示例:分段内存管理

        分段内存管理可以将内存分成多个固定大小的段,每次分配或释放内存时操作这些段,而不是操作整个数组。这种方法适用于需要频繁分配和释放内存的场景。

class SegmentedDynamicArray:def __init__(self, segment_size=4):self.segment_size = segment_sizeself.segments = [[]]self.size = 0def append(self, element):if len(self.segments[-1]) == self.segment_size:self.segments.append([])self.segments[-1].append(element)self.size += 1def get(self, index):if not 0 <= index < self.size:raise IndexError("index out of bounds")segment_index = index // self.segment_sizeelement_index = index % self.segment_sizereturn self.segments[segment_index][element_index]def delete(self):if self.size == 0:raise IndexError("delete from empty array")self.segments[-1].pop()self.size -= 1if len(self.segments[-1]) == 0:self.segments.pop()def __len__(self):return self.sizedef __str__(self):return str([elem for segment in self.segments for elem in segment])# 测试分段内存管理的柔性数组
segmented_array = SegmentedDynamicArray(segment_size=3)
segmented_array.append(1)
segmented_array.append(2)
segmented_array.append(3)
segmented_array.append(4)
print("Segmented array after appending 1, 2, 3, 4:", segmented_array)segmented_array.delete()
print("Segmented array after deleting last element:", segmented_array)
2. 多线程环境下的并发处理

        在多线程环境中使用柔性数组时,需要考虑线程安全问题。可以使用锁机制(如互斥锁)来确保线程安全。

示例:线程安全的柔性数组
import threadingclass ThreadSafeDynamicArray:def __init__(self):self.lock = threading.Lock()self.capacity = 1self.size = 0self.array = [None] * self.capacitydef _resize(self, new_capacity):with self.lock:new_array = [None] * new_capacityfor i in range(self.size):new_array[i] = self.array[i]self.array = new_arrayself.capacity = new_capacitydef append(self, element):with self.lock:if self.size == self.capacity:self._resize(2 * self.capacity)self.array[self.size] = elementself.size += 1def get(self, index):with self.lock:if not 0 <= index < self.size:raise IndexError("index out of bounds")return self.array[index]def delete(self):with self.lock:if self.size == 0:raise IndexError("delete from empty array")self.array[self.size - 1] = Noneself.size -= 1if 0 < self.size < self.capacity // 4:self._resize(self.capacity // 2)def __len__(self):with self.lock:return self.sizedef __str__(self):with self.lock:return str([self.array[i] for i in range(self.size)])# 测试线程安全的柔性数组
thread_safe_array = ThreadSafeDynamicArray()
thread_safe_array.append(1)
thread_safe_array.append(2)
print("Thread-safe array after appending 1, 2:", thread_safe_array)

结合算法和数据结构实现实际应用

示例:实现优先队列(Priority Queue)

        优先队列是一种元素具有优先级的数据结构,通常使用堆(Heap)来实现。这里我们结合柔性数组实现一个简单的优先队列。

实现优先队列
class PriorityQueue:def __init__(self):self.heap = DynamicArray()def _parent(self, index):return (index - 1) // 2def _left_child(self, index):return 2 * index + 1def _right_child(self, index):return 2 * index + 2def _heapify_up(self, index):parent_index = self._parent(index)if index > 0 and self.heap.get(index) > self.heap.get(parent_index):self.heap.array[index], self.heap.array[parent_index] = self.heap.array[parent_index], self.heap.array[index]self._heapify_up(parent_index)def _heapify_down(self, index):left_child_index = self._left_child(index)right_child_index = self._right_child(index)largest = indexif left_child_index < len(self.heap) and self.heap.get(left_child_index) > self.heap.get(largest):largest = left_child_indexif right_child_index < len(self.heap) and self.heap.get(right_child_index) > self.heap.get(largest):largest = right_child_indexif largest != index:self.heap.array[index], self.heap.array[largest] = self.heap.array[largest], self.heap.array[index]self._heapify_down(largest)def insert(self, element):self.heap.append(element)self._heapify_up(len(self.heap) - 1)def extract_max(self):if len(self.heap) == 0:raise IndexError("extract from empty priority queue")max_element = self.heap.get(0)last_element = self.heap.get(len(self.heap) - 1)self.heap.array[0] = last_elementself.heap.delete()self._heapify_down(0)return max_elementdef __len__(self):return len(self.heap)def __str__(self):return str(self.heap)# 测试优先队列
priority_queue = PriorityQueue()
priority_queue.insert(10)
priority_queue.insert(20)
priority_queue.insert(15)
print("Priority queue after inserting 10, 20, 15:", priority_queue)max_element = priority_queue.extract_max()
print("Extracted max element:", max_element)
print("Priority queue after extracting max element:", priority_queue)

实际应用场景

  1. 动态数据存储:在应用程序中需要存储可变长度的数据时,柔性数组是一个理想选择,如动态表格、实时数据流处理等。
  2. 内存管理:操作系统和数据库系统中,经常使用柔性数组管理内存块和数据块,以提高内存利用效率。
  3. 实时系统:在需要快速响应的数据处理系统中,柔性数组的动态扩展和缩减能力非常重要。

总结

        通过更深入的优化和复杂应用场景的探讨,我们了解了柔性数组的广泛应用和性能优化策略。无论是在多线程环境下的并发处理,还是在实现高级数据结构(如优先队列)时,柔性数组都展现了其灵活性和高效性。继续探索和优化这些数据结构,将为我们在实际项目中解决复杂问题提供更多有效的工具和方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/843739.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

鸿蒙OS 路由跳转

路由跳转 在鸿蒙开发中&#xff0c;路由跳转是页面之间进行切换的基本方式。以下是一些常见的路由跳转方法&#xff1a; 1. **使用Route装饰器**&#xff1a;在需要跳转的页面上添加Route装饰器&#xff0c;并指定一个唯一的路由路径。例如&#xff1a; java Route(path "…

Sentinel-2 哨兵二号数据介绍及下载

1 Sentinel-2简介 SENTINEL-2 is a European wide-swath, high-resolution, multi-spectral imaging mission. Sentinel-2 是高分辨率多光谱成像卫星&#xff0c;一颗卫星的重访周期为10天&#xff0c;两颗互补&#xff0c;重访周期为5天。分为2A和2B两颗卫星。2A于2015年6月…

可燃气体报警器检测周期:如何合理设定以满足安全需求?

可燃气体报警器作为工业安全和生产环境中不可或缺的安全防护设备&#xff0c;其准确性、稳定性和及时响应性对于防止火灾和爆炸事故具有重要意义。 因此&#xff0c;合理设定并严格执行可燃气体报警器的检测周期&#xff0c;是确保安全与可靠运行的核心环节。 一、检测周期的重…

速盾:cdn命中率低解决方案

CDN&#xff08;Content Delivery Network&#xff09;是一种分布式的网络架构&#xff0c;通过将内容存储在离用户更近的节点上&#xff0c;提供快速的内容传输和低延迟。CDN的命中率是指用户请求的内容能够在CDN节点上找到并传输给用户的比例。如果CDN的命中率低&#xff0c;…

Ubuntu16.04系统配置mariDB,QT连接数据库(小白通关)

两个方法: 1.从官方镜像下载MariaDB 2.从ubuntu仓库下载MariaDB Ubuntu 18.04 的主软件源中包含了适用于 Ubuntu 18.04 的最新版本 MariaDB 10.1。因此,我们建议在 Ubuntu 18.04 上使用 Ubuntu 代码库安装 MariaDB。 我们建议不要在 Ubuntu 16.04 上安装 Ubuntu 代码库中…

蓝桥杯单片机省赛程序题目

文章目录 链接过往历程省赛代码传送门 链接 链接&#xff1a;https://pan.baidu.com/s/15KRZ_Jo3DeHJg1wBuQJk1w?pwdodkt 提取码&#xff1a;odkt 过往历程 历程1&#xff1a;秒表 历程2&#xff1a;按键显示时钟 历程3&#xff1a;列矩阵按键显示时钟 历程4&#xff1a…

c 声明、定义、初始化的差别

在C语言中&#xff0c;声明&#xff08;declaration&#xff09;、定义&#xff08;definition&#xff09;和初始化&#xff08;initialization&#xff09;是三个重要的概念&#xff0c;它们之间有一些明显的差别。以下是它们之间的主要区别&#xff1a; 声明&#xff08;De…

使用阿里云OSS实现视频上传功能

目录 前言 视频上传 前言 阿里云对象存储服务&#xff08;OSS&#xff09;作为一种高可用、高扩展性的云端存储服务&#xff0c;为开发者提供了便捷、安全的对象存储解决方案。本文将介绍如何利用阿里云OSS实现视频上传功能。 视频上传 前期准备请看阿里云OSS文件上传和下载…

浙江大学数据结构MOOC-课后习题-第九讲-排序2 Insert or Merge

题目汇总 浙江大学数据结构MOOC-课后习题-拼题A-代码分享-2024 题目描述 测试点 思路分析 刚开始我打算想推出一个规律&#xff0c;来判断是否是归并排序&#xff0c;但实在太过于复杂&#xff0c;我很难去想出这样的规律…因此&#xff0c;参考了其他博主的思路——每做一次排…

【微服务】安装docker以及可视化界面

1.配置yum下载源为aliyun源 yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo2.下载docker不加版本号默认为最新版本 yum install -y docker-ce3.启动以及开机自启 #启动docker命令 systemctl start docker #设置开机自启命令…

计算机组成原理----原码,反码与补码

目录 1.原码的出现 2.反码的出现 3.补码的出现 4.关于补码 1.原码的出现 我们通常使用"","-"判断数字的正负,而在计算机中,则将二进制的首位当作标记符号,"0"表示正数,"1"表示负数,这样就解决了在计算机中表示数值正负的问题,唯一…

allure测试报告用例数和 pytest执行用例数不相同问题

我出现的奇怪问题: pytest执行了9条用例,但是测试报告确只显示3条用例 我将其中的一个代码删除后,发现allure测试报告又正常了 我觉得很奇怪这个代码只是删除了二维数组的第一列,我检查了半天都找不到问题,只有降低版本了。导致原因:allure-pytest版本使用的是最新版本,…

编译安装python(3.9.2)

python源码下载地址https://www.python.org/ftp/python/ 编译安装python 安装构建工具&#xff1a; sudo apt-get update sudo apt-get install build-essential安装Python的依赖项&#xff1a; sudo apt-get install zlib1g-dev下载并编译Python&#xff1a; wget https://www…

机器学习-3-特征工程的重要性及常用特征选择方法

参考特征重要性:理解机器学习模型预测中的关键因素 参考[数据分析]特征选择的方法 1 特征重要性 特征重要性帮助我们理解哪些特征或变量对模型预测的影响最大。 特征重要性是数据科学中一个至关重要的概念,尤其是在建立预测性任务的模型时。想象你正在尝试预测明天是否会下…

ubuntu中idea创建spark项目步骤

1.前置条件 ubuntu中已经安装idea,jdk,scala,spark 2.打开idea&#xff0c;新建&#xff0c;选择Maven项目 3.在IDEA中&#xff0c;File-Setting-Plugin&#xff0c;下载Scala插件 4.File-project structure&#xff0c;导入插件 4.1在全局库中&#xff0c;选择导入刚才的sca…

写论文时某一行的字间距突然增大,如何解决?

问题描述&#xff1a; 某一行的字间距突然变大&#xff0c;占满了一行&#xff0c;检查设置也没有异常。 如何解决 一、全选出现问题的段落 二、右键&#xff0c;然后点击段落 三、然后勾选允许西文在单词中间换行 四、正常了

心链4---搜索页面前后端业务实现以及分布式session的共享实现

心链 — 伙伴匹配系统 搜索详情页面 之前前端的代码写到了搜索页面可以挑选搜索标签&#xff0c;并没有去根据具体标签搜索用户。这里就开始实现。 新建SearchResultPage.vue&#xff0c;并添加相关路由。 在搜索页添加搜索按钮&#xff0c;和触发点击。搜索页选择标签&#x…

WEB安全:Content Security Policy (CSP) 详解

Content Security Policy (CSP) 是一种强大的网页安全机制,用于防止跨站脚本 (XSS) 和其他注入攻击。通过设置一系列的内容安全策略,CSP 可以限制网页可以加载的资源,从而保护用户数据和网站的安全性。 什么是 XSS 攻击? 跨站脚本攻击 (XSS) 是一种常见的安全漏洞,攻击者…

闲鱼电商运营高级课程,一部手机学会闲鱼开店赚钱

课程下载&#xff1a;https://download.csdn.net/download/m0_66047725/89360471 更多资源下载&#xff1a;关注我。 课程内容&#xff1a; 10-9、怎么寻找优质的货源店铺.mp4 11-10、怎么去选择商品图片.mp4 12-11、商品图片的注意避免事项.mp4 13-12、怎么写标题.mp4 …

【Mybatis】映射文件中获取单个参数和多个参数的写法

xml的映射文件中获取接口方法中传来的参数是直接用#{}的方式来获取的 那么接下来&#xff0c;我们就具体来说一下获取参数里边的各种规则和用法 1.单个参数&#xff0c;比如上面的getOneUser&#xff0c;只有一个id值作为参数 Mybatis对于只有一个参数的情况下&#xff0c;不…