栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

数据结构与算法----学习笔记(2)数组理论部分

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

数据结构与算法----学习笔记(2)数组理论部分

数组:将数据元素顺序的存储在一片连续的存储区里,元素之间的顺序关系由它们的存储顺序决定
数组最大的优点:可以快速查询


自定义一个数组

静态数组的实现
静态数组是指数组的容量是固定的,

class Array:
    def __init__(self, capacity=10):
        self._capacity = capacity
        self._size = 0
        self._data = [None] * self._capacity  # 构造一段连续的固定空间

    def __getitem__(self, item):
        # 使数组支持索引操作
        return self._data[item]

    def getSize(self):
        return self._size

    def getCapacity(self):
        return self._capacity

    def isEmpty(self):
        return self._size == 0

    def addLast(self, elem):
        if self._size == self._capacity:
            raise Exception("array已经满了,不能再往里添加元素!")
        self._data[self._size] = elem
        self._size += 1
        # 可以直接调用add函数
        # self.add(self._size,elem)

    def add(self, index, elem):
        if index < 0 or index > self._size:
            raise Exception("索引值错误!")
        if self._size == self._capacity:
            raise Exception("array已经满了,不能再往里添加元素!")
        for i in range(self._size, index, -1):  # 这里i不能到index,只能到inde+1
            self._data[i] = self._data[i - 1]
            # 注意这里就算是插入的位置为0,不能哪种方法实现,都可以,因为range不包含最后一个数
        # for i in range(self._size-1,index-1,-1):
        #     self._data[i+1] = self._data[i]
        self._data[index] = elem
        self._size += 1

    def addFirst(self, elem):
        self.add(0, elem)

    def get(self, index):
        if index < 0 or index >= self._size:
            # 判断索引的时候要列表大小,因为索引值最大为元素长度-1
            raise Exception("索引值错误!")
        return self._data[index]

    def getFirst(self):
        return self.get(0)

    def getLast(self):
        return self.get(self._size - 1)

    def set(self, index, elem):
        if index < 0 or index >= self._size:
            raise Exception("索引错误!")
        self._data[index] = elem

    def contains(self, ele):
        for i in range(self._size):
            if self._data[i] == ele:
                return True
        return False

    def find(self, ele):
        for i in range(self._size):
            if self._data[i] == ele:
                return i
        return -1

    def findAll(self, ele):
        res = Array()
        for i in range(self._size):
            if self._data[i] == ele:
                res.addLast(i)
        return res

    def remove(self, index):
        if index < 0 or index >= self._size:
            # 对于空列表,移除0位置,则index>=self._size成立
            raise Exception("索引错误!")
        ret = self._data[index]
        for i in range(index, self._size + 1):
            self._data[i] = self._data[i + 1]
        self._size -= 1
        return ret

    def removeFirst(self):
        return self.remove(0)

    def removeLast(self):
        return self.remove(self._size - 1)

    def removeElement(self, elem):
        index = self.find(elem)
        if index != -1:
            self.remove(index)
        else:
            print("该元素在列表中不存在!")

    def removeAllElement(self, elem):
        while True:
            index = self.find(elem)
            if index != -1:
                self.remove(index)
            else:
                break

    def get_Max_index(self):
        if self.isEmpty():
            raise Exception("这是一个空列表,没有最大值!")
        max_elem_index = 0
        for i in range(1, self._size):
            if self._data[i] > self._data[max_elem_index]:
                max_elem_index = i
        return max_elem_index

    def removeMax(self):
        index = self.get_Max_index()
        return self.remove(index)

    def get_Min_index(self):
        if self.isEmpty():
            raise Exception("这是一个空列表,没有最大值!")
        min_elem_index = 0
        for i in range(1, self._size):
            if self._data[i] < self._data[min_elem_index]:
                min_elem_index = i
        return min_elem_index

    def removeMin(self):
        return self.remove(self.get_Min_index())

    def swap(self, index1, index2):
        if index1 < 0 or index1 >= self._size or index2 < 0 or index2 >= self._size:
            raise Exception("索引错误!")
        self._data[index1], self._data[index2] = self._data[index2], self._data[index1]

    def printArr(self):
        for i in range(self._size):
            print(self._data[i], end=' ')
        print('nSize:%d-----------Capacity:%d' % (self.getSize(), self.getCapacity()))

动态数组
class Array:
    def __init__(self, capacity=10):
        self._capacity = capacity
        self._size = 0
        self._data = [None] * self._capacity  # 构造一段连续的固定空间

    def __getitem__(self, item):
        # 使数组支持索引操作
        return self._data[item]

    def getSize(self):
        return self._size

    def getCapacity(self):
        return self._capacity

    def isEmpty(self):
        return self._size == 0

    def addLast(self, elem):
        self.add(self._size, elem)
	# 和静态数组的最大区别就是添加了一个resize操作
    def _resize(self, new_capacity):
        new_arr = Array(new_capacity)
        for i in range(self._size):
            new_arr.addLast(self._data[i])
        self._capacity = new_capacity
        self._data = new_arr._data

    def add(self, index, elem):
        if index < 0 or index > self._size:
            raise Exception("索引值错误!")
        if self._size == self._capacity:
            self._resize(self._capacity * 2)

            # raise Exception("array已经满了,不能再往里添加元素!")
        for i in range(self._size, index, -1):  # 这里i不能到index,只能到inde+1
            self._data[i] = self._data[i - 1]
            # 注意这里就算是插入的位置为0,不能哪种方法实现,都可以,因为range不包含最后一个数
        # for i in range(self._size-1,index-1,-1):
        #     self._data[i+1] = self._data[i]
        self._data[index] = elem
        self._size += 1

    def addFirst(self, elem):
        self.add(0, elem)

    def get(self, index):
        if index < 0 or index >= self._size:
            # 判断索引的时候要列表大小,因为索引值最大为元素长度-1
            raise Exception("索引值错误!")
        return self._data[index]

    def getFirst(self):
        return self.get(0)

    def getLast(self):
        return self.get(self._size - 1)

    def set(self, index, elem):
        if index < 0 or index >= self._size:
            raise Exception("索引错误!")
        self._data[index] = elem

    def contains(self, ele):
        for i in range(self._size):
            if self._data[i] == ele:
                return True
        return False

    def find(self, ele):
        for i in range(self._size):
            if self._data[i] == ele:
                return i
        return -1

    def findAll(self, ele):
        res = Array()
        for i in range(self._size):
            if self._data[i] == ele:
                res.addLast(i)
        return res

    def remove(self, index):
        if index < 0 or index >= self._size:
            # 对于空列表,移除0位置,则index>=self._size成立
            raise Exception("索引错误!")
        ret = self._data[index]
        for i in range(index, self._size + 1):
            self._data[i] = self._data[i + 1]
        self._size -= 1
        #可能会引起后文提到的复杂度震荡,因此将缩容时候更改为1/4时再缩容
        #if self._size and self._capacity // self._size == 2:
        if self._size and self._capacity // self._size == 4:
            self._resize(self._capacity // 2)
        return ret

    def removeFirst(self):
        return self.remove(0)

    def removeLast(self):
        return self.remove(self._size - 1)

    def removeElement(self, elem):
        index = self.find(elem)
        if index != -1:
            self.remove(index)
        else:
            print("该元素在列表中不存在!")

    def removeAllElement(self, elem):
        while True:
            index = self.find(elem)
            if index != -1:
                self.remove(index)
            else:
                break

    def get_Max_index(self):
        if self.isEmpty():
            raise Exception("这是一个空列表,没有最大值!")
        max_elem_index = 0
        for i in range(1, self._size):
            if self._data[i] > self._data[max_elem_index]:
                max_elem_index = i
        return max_elem_index

    def removeMax(self):
        index = self.get_Max_index()
        return self.remove(index)

    def get_Min_index(self):
        if self.isEmpty():
            raise Exception("这是一个空列表,没有最大值!")
        min_elem_index = 0
        for i in range(1, self._size):
            if self._data[i] < self._data[min_elem_index]:
                min_elem_index = i
        return min_elem_index

    def removeMin(self):
        return self.remove(self.get_Min_index())

    def swap(self, index1, index2):
        if index1 < 0 or index1 >= self._size or index2 < 0 or index2 >= self._size:
            raise Exception("索引错误!")
        self._data[index1], self._data[index2] = self._data[index2], self._data[index1]

    def printArr(self):
        for i in range(self._size):
            print(self._data[i], end=' ')
        print('nSize:%d-----------Capacity:%d' % (self.getSize(), self.getCapacity()))

时间复杂度:
对于数组而言,时间复杂度中所指的n是该数组中元素的个数
增、删:O(n)
对于增删,如果在最后一个位置增删的话,时间复杂度为O(1),但是如果调用了resize操作,那么时间复杂度就是O(n),因此最坏时间复杂度就是O(n)

改:已知索引O(1)、未知索引O(n)
查:已知索引O(1)、未知索引O(n)
一般说的时间复杂度都是指最坏时间复杂度


动态数组均摊复杂度

如果每次只是在数组的最后一个位置添加
例如,capacity=8,添加8次该数组满了,添加第九次的时候,触发了resize,那么进行了8次的元素转移,总共9次添加+8次数据转移
capacity=m,m+1次添加,m次转移,总共进行了2m+1次基本操作,平均每次添加操作进行2次基本操作,即均摊复杂度为O(1)
总之,多少次触发一次O(n) ,那么这几次操作均摊这O(n)

复杂度震荡

对于动态数组,如果数组满了,那么就会触发resize操作进行扩容,容量变成原来的2倍,刚刚扩容后紧接着进行删除一个元素,那么,这是元素的个数<=容量的1/2,又将会进行缩容,这样每次都将进行时间复杂度为O(n) 的操作


Python列表与字典操作的时间复杂度



注意,contains的时间复杂度为O(1)

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/829745.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号