python實現(xiàn)動態(tài)數(shù)組的示例代碼
更新時間:2019年07月15日 10:40:50 作者:吱吱不倦小子
這篇文章主要介紹了python實現(xiàn)動態(tài)數(shù)組的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
實現(xiàn)一個支持動態(tài)擴容的數(shù)組并完成其增刪改查
#通過python實現(xiàn)動態(tài)數(shù)組
"""
數(shù)組特點:
占用一段連續(xù)的內(nèi)存空間,支持隨機(索引)訪問,且時間復雜度為O(1)
添加元素時間復雜度:O(n)
刪除元素時間復雜度:O(n)
"""
class Arr:
def __init__(self, capacity=10):
"""
構(gòu)造函數(shù)
:param capacity: 數(shù)組最大容量,不指定的話默認為10
"""
self._capacity = capacity
self._size = 0 # 數(shù)組有效元素的數(shù)目,初始化為0
self._data = [None] * self._capacity # 由于python的list是動態(tài)擴展的,而我們要實現(xiàn)底層具有固定容量、占用一段連續(xù)的內(nèi)存空間的數(shù)組,所以用None來作為無效元素的標識
def __getitem__(self, item):
"""讓Arr類支持索引操作"""
return self._data[item]
def getSize(self):
"""返回數(shù)組有效元素的個數(shù)"""
return self._size
def getCapacity(self):
"""返回當前數(shù)組的容量"""
return self._capacity
def isEmpty(self):
"""判斷當前數(shù)組是否為空"""
return self._size == 0
def add(self, index, elem):
"""
向數(shù)組中添加一個元素,注意數(shù)組占用的是一段連續(xù)的內(nèi)存空間,所以在添加元素后,數(shù)組還是要保證這個特點的,因此需要將后面的元素都向后挪一個位置,而且要注意要先從
尾部開始挪,防止元素之間的覆蓋
時間復雜度:O(n)
:param index: 添加的元素所在的索引
:param elem: 所要添加的元素
"""
if index < 0 or index > self._size: # 插入的位置無效
raise Exception('Add Filed. Require 0 <= index <= self._size')
if self._size == self._capacity: # 滿了
self._resize(self._capacity * 2) # 默認擴容當前容量的二倍。容量翻倍要比容量加上一個固定值要好,這樣做均攤復雜度為O(1)。具體請百度
for i in range(self._size - 1, index - 1, -1): # 從尾部開始挪動元素,在index處騰出一個空間
# 一定要注意在步長為負數(shù)的情況下,區(qū)間是左開右閉區(qū)間,即(index, self._size - 1],所以是index-1,與正常的左閉右開區(qū)間是相反的!
self._data[i + 1] = self._data[i]
self._data[index] = elem # 將該位置賦值為elem
self._size += 1 # 數(shù)組有效元素數(shù)加1
def addLast(self, elem):
"""
向數(shù)組尾部添加元素
時間復雜度:O(1)
:param elem: 所要添加的元素
"""
self.add(self._size, elem) # 直接調(diào)用add方法,注意不用再次判定合法性了,因為add函數(shù)中已經(jīng)判斷過了
def addFirst(self, elem):
"""
想數(shù)組頭部添加元素
時間復雜度:O(n)
:param elem: 所要添加的元素
"""
self.add(0, elem) # 同理直接調(diào)用add方法
def get(self, index):
"""
獲得索引index處的元素
時間復雜度:O(1)
:param index: 數(shù)組索引
:return: 數(shù)組索引處的值
"""
if index < 0 or index >= self._size: # 判斷index的合法性
raise Exception('Get failed. Index is illegal.')
return self._data[index]
def getFirst(self):
"""
獲得數(shù)組首位置元素的值
:return: 首位置元素的值
"""
return self.get(0) # 直接調(diào)用get函數(shù),安全可靠
def getLast(self):
"""
獲得數(shù)組末尾元素的值
:return: 末尾元素的值
"""
return self.get(self._size - 1) # 直接調(diào)用get函數(shù),安全可靠
def set(self, index, elem):
"""
將索引為index的元素的值設為elem
時間復雜度:O(1)
:param index: 索引
:param elem: 新的值
"""
if index < 0 or index >= self._size: # 判斷index的合法性
raise Exception('Sat failed. Index is illegal.')
self._data[index] = elem
def contains(self, elem):
"""
查看數(shù)組中是否存在元素elem,最好不要傳入一個浮點數(shù),你懂得。。
時間復雜度:O(n)
:param elem: 目標元素
:return: bool值,存在為真
"""
for i in range(self._size): # 遍歷
if self._data[i] == elem:
return True # 找到了就返回True
return False # 遍歷完了還沒找到,就返回False
def find(self, elem):
"""
在數(shù)組中查找元素,并返回元素所在的索引。(如果數(shù)組中存在多個elem,只返回最左邊elem的索引)
時間復雜度:O(n)
:param elem: 目標元素
:return: 元素所在的索引,沒找到則返回-1(無效值)
"""
for i in range(self._size): # 遍歷數(shù)組
if self._data[i] == elem:
return i # 找到就返回索引
return -1 # 沒找到返回-1
def findAll(self, elem):
"""
找到值為elem全部元素的索引
:param elem: 目標元素
:return: 一個列表,值為全部elem的索引
"""
ret_list = Arr() # 建立一個新的數(shù)組用于存儲索引值
for i in range(self._size): # 遍歷數(shù)組
if self._data[i] == elem:
ret_list.addLast(i) # 找到就將索引添加進ret_list
return ret_list
def remove(self, index):
"""
刪除索引為index的元素。index后面的元素都要向前移動一個位置
時間復雜度:O(n)
:param index: 目標索引
:return: 位于該索引的元素的值
"""
if index < 0 or index >= self._size: # index合法性檢查
raise Exception('Remove failed.Require 0 <= index < self._size')
ret = self._data[index] # 拷貝一下index處的元素,便于返回
for i in range(index + 1, self._size): # index后面的元素都向前挪一個位置
self._data[i - 1] = self._data[i]
self._size -= 1 # 維護self._size
self._data[self._size] = None # 最后一個元素的垃圾回收
if self._size and self._capacity // self._size == 4: # 如果當前有效元素為總?cè)萘康乃姆种磺疫€存在有效元素,則將容量縮減為原來的一半
self._resize(self._capacity // 2)
return ret
def removeFirst(self):
"""
刪除數(shù)組首位置的元素
時間復雜度:O(n)
:return: 數(shù)組首位置的元素
"""
return self.remove(0) # 調(diào)用remove函數(shù)
def removeLast(self):
"""
刪除數(shù)組末尾的元素
時間復雜度:O(1)
:return: 數(shù)組末尾的元素
"""
return self.remove(self._size - 1) # 調(diào)用remove函數(shù)
def removeElement(self, elem):
"""
刪除數(shù)組中為elem的元素,如果數(shù)組中不存在elem,那么什么都不做。如果存在多個相同的elem,只刪除最左邊的那個
時間復雜度:O(n)
:param elem: 要刪除的目標元素
"""
index = self.find(elem) # 嘗試找到目標元素(最左邊的)的索引
if index != -1: # elem在數(shù)組中就刪除,否則什么都不做
self.remove(index) # 調(diào)用remove函數(shù)
def removeAllElement(self, elem):
"""
刪除數(shù)組內(nèi)所有值為elem的元素,可以用遞歸來寫,這里用的迭代的方法。elem不存在就什么都不做
:param elem: 要刪除的目標元素
"""
while True:
index = self.find(elem) # 循環(huán)來找elem,如果還存在就繼續(xù)刪除
if index != -1: # 若存在
self.remove(index)
else:
break
def get_Max_index(self):
"""
獲取數(shù)組中的最大元素的索引,返回最大元素的索引值,如果有多個最大值,默認返回最左邊那個的索引
時間復雜度:O(n)
:return: 最大元素的索引
"""
if self.isEmpty():
raise Exception('Error, array is Empty!')
max_elem_index = 0 # 記錄最大值的索引,初始化為0
for i in range(1, self.getSize()): # 從索引1開始遍歷,一直到數(shù)組尾部
if self._data[i] > self._data[max_elem_index]: # 如果當前索引的值大于最大值索引處元素的值
max_elem_index = i # 更新max_elem_index,這樣它還是當前最大值的索引
return max_elem_index # 遍歷完后,將數(shù)組的最大值的索引返回
def removeMax(self):
"""
刪除數(shù)組中的最大元素,返回最大元素的值,如果有多個最大值,默認值刪除最左邊那個
時間復雜度:O(n)
:return: 最大元素
"""
return self.remove(self.get_Max_index()) # 直接調(diào)用remove函數(shù)刪除最大值
def get_Min_index(self):
"""
獲取數(shù)組中的最小元素的索引,返回最小元素的索引值,如果有多個最小值,默認返回最左邊那個的索引
時間復雜度:O(n)
:return: 最小元素的索引
"""
if self.isEmpty():
raise Exception('Error, array is Empty!')
min_elem_index = 0 # 記錄最小值的索引,初始化為0
for i in range(1, self.getSize()): # 從索引1開始遍歷,一直到數(shù)組尾部
if self._data[i] < self._data[min_elem_index]: # 如果當前索引的值小于最小值索引處元素的值
min_elem_index = i # 更新min_elem_index,這樣它還是當前最小值的索引
return min_elem_index # 遍歷完后,將數(shù)組的最小值的索引返回
def removeMin(self):
"""
刪除數(shù)組中的最小元素,返回最小元素的值,如果有多個最小值,默認值刪除最左邊那個
時間復雜度:O(2n),可以看成是O(n)的
:return: 最小元素
"""
return self.remove(self.get_Min_index())
def swap(self, index1, index2):
"""
交換分別位于索引index1和索引index2處的元素
:param index1: 索引1
:param index2: 索引2
"""
if index1 < 0 or index2 < 0 or index1 >= self._size or index2 >= self._size: # 合法性檢查
raise Exception('Index is illegal')
self._data[index1], self._data[index2] = self._data[index2], self._data[index1] # 交換元素
def printArr(self):
"""對數(shù)組元素進行打印"""
for i in range(self._size):
print(self._data[i], end=' ')
print('\nSize: %d-----Capacity: %d' % (self.getSize(), self.getCapacity()))
# private
def _resize(self, new_capacity):
"""
數(shù)組容量放縮至new_capacity,私有成員函數(shù)
:param new_capacity: 新的容量
"""
new_arr = Arr(new_capacity) # 建立一個新的數(shù)組new_arr,容量為new_capacity
for i in range(self._size):
new_arr.addLast(self._data[i]) # 將當前數(shù)組的元素按當前順序全部移動到new_arr中
self._capacity = new_capacity # 數(shù)組容量變?yōu)閚ew_capacity
self._data = new_arr._data # 將new_arr._data賦值給self._data,從而完成數(shù)組的容量放縮操作
測試代碼
import Array import numpy as np np.random.seed(7) test = Array.Arr() print(test.getSize()) print(test.getCapacity()) print(test.isEmpty()) for i in range(8): test.add(0, np.random.randint(5)) test.printArr() test.addLast(2) test.printArr() print(test.get(3)) test.set(3, 10) test.printArr() print(test.contains(10)) print(test.find(4)) test.findAll(1).printArr() test.remove(3) test.printArr() test.removeFirst() test.removeLast() test.printArr() test.removeElement(4) test.printArr() test.removeAllElement(3) test.printArr() for i in range(30): test.addLast(np.random.randint(10)) test.printArr() print(test[3]) test.swap(0, 1) test.printArr()
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
您可能感興趣的文章:
- Python動態(tài)生成多維數(shù)組的方法示例
- Python 取numpy數(shù)組的某幾行某幾列方法
- 詳細整理python 字符串(str)與列表(list)以及數(shù)組(array)之間的轉(zhuǎn)換方法
- Python3之字節(jié)串bytes與字節(jié)數(shù)組bytearray的使用詳解
- python數(shù)組循環(huán)處理方法
- 對Python 中矩陣或者數(shù)組相減的法則詳解
- python切片(獲取一個子列表(數(shù)組))詳解
- 詳解Python Matplotlib解決繪圖X軸值不按數(shù)組排序問題
- Python如何實現(xiàn)動態(tài)數(shù)組
相關(guān)文章
簡單了解python gevent 協(xié)程使用及作用
這篇文章主要介紹了簡單了解python gevent 協(xié)程,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2019-07-07
python Pandas中數(shù)據(jù)的合并與分組聚合
大家好,本篇文章主要講的是python Pandas中數(shù)據(jù)的合并與分組聚合,感興趣的同學趕快來看一看吧,對你有幫助的話記得收藏一下2022-01-01
Python+OpenCV內(nèi)置方法實現(xiàn)行人檢測
OpenCV附帶一個預訓練的HOG+線性SVM模型,可用于在圖像和視頻流中執(zhí)行行人檢測。本文我們將使用Opencv自帶的模型實現(xiàn)對視頻流中的行人檢測。感興趣的小伙伴可以跟隨小編一起學習一下2021-12-12
python socket 超時設置 errno 10054
這篇文章主要介紹了python 遠程主機強迫關(guān)閉了一個現(xiàn)有的連接 socket 超時設置 errno 10054 ,需要的朋友可以參考下2014-07-07

