数组理论,列表,字典

数组 一直是我学Python中比较困惑的部分,一直以为是内置的数据类型了,后来才发现并不是,需要自己去定义这类写问题。

  1. 数组定义
  2. 向数组中增加元素
  3. 数组中查询元素和修改元素
  4. 数组中包含、搜索、删除元素、
  5. 动态数组时间复杂度分析
#通过python实现动态数组
 
"""
数组特点:
    占用一段连续的内存空间,支持随机(索引)访问,且时间复杂度为O(1)
    添加元素时间复杂度:O(n)
    删除元素时间复杂度:O(n)
"""
 
class Arr:
    def __init__(self, capacity=10):
        """
        构造函数
        :param capacity: 数组最大容量,不指定的话默认为10
        """
        self._capacity = capacity
        self._size = 0                                  # 数组有效元素的数目,初始化为0
        self._data = [None] * self._capacity    # 由于python的list是动态扩展的,而我们要实现底层具有固定容量、占用一段连续的内存空间的数组,所以用None来作为无效元素的标识
 
    def __getitem__(self, item):
        """让Arr类支持索引操作"""
        return self._data[item]
 
    def getSize(self):
        """返回数组有效元素的个数"""
        return self._size
 
    def getCapacity(self):
        """返回当前数组的容量"""
        return self._capacity
 
    def isEmpty(self):
        """判断当前数组是否为空"""
        return self._size == 0
 
    def add(self, index, elem):
        """
        向数组中添加一个元素,注意数组占用的是一段连续的内存空间,所以在添加元素后,数组还是要保证这个特点的,因此需要将后面的元素都向后挪一个位置,而且要注意要先从
        尾部开始挪,防止元素之间的覆盖
        时间复杂度: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处腾出一个空间
                                                        # 一定要注意在步长为负数的情况下,区间是左开右闭区间,即(index, self._size - 1],所以是index-1,与正常的左闭右开区间是相反的!
            self._data[i + 1] = self._data[i]
        self._data[index] = elem        # 将该位置赋值为elem
        self._size += 1                 # 数组有效元素数加1
 
    def addLast(self, elem):
        """
        向数组尾部添加元素
        时间复杂度:O(1)
        :param elem: 所要添加的元素
        """
        self.add(self._size, elem) # 直接调用add方法,注意不用再次判定合法性了,因为add函数中已经判断过了
 
    def addFirst(self, elem):
        """
        想数组头部添加元素
        时间复杂度:O(n)
        :param elem: 所要添加的元素
        """
        self.add(0, elem)   # 同理直接调用add方法
 
    def get(self, index):
        """
        获得索引index处的元素
        时间复杂度:O(1)
        :param index: 数组索引
        :return:      数组索引处的值
        """
        if index < 0 or index >= self._size:        # 判断index的合法性
            raise Exception('Get failed. Index is illegal.')
        return self._data[index]
 
    def getFirst(self):
        """
        获得数组首位置元素的值
        :return: 首位置元素的值
        """
        return self.get(0)      # 直接调用get函数,安全可靠
 
    def getLast(self):
        """
        获得数组末尾元素的值
        :return: 末尾元素的值
        """
        return self.get(self._size - 1)  # 直接调用get函数,安全可靠
 
    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):
        """
        查看数组中是否存在元素elem,最好不要传入一个浮点数,你懂得。。
        时间复杂度: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):
        """
        在数组中查找元素,并返回元素所在的索引。(如果数组中存在多个elem,只返回最左边elem的索引)
        时间复杂度:O(n)
        :param elem: 目标元素
        :return:     元素所在的索引,没找到则返回-1(无效值)
        """
        for i in range(self._size):         # 遍历数组
            if self._data[i] == elem:
                return i                    # 找到就返回索引
        return -1                           # 没找到返回-1
 
    def findAll(self, elem):
        """
        找到值为elem全部元素的索引
        :param elem: 目标元素
        :return:     一个列表,值为全部elem的索引
        """
        ret_list = Arr()                # 建立一个新的数组用于存储索引值
        for i in range(self._size):     # 遍历数组
            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:   # 如果当前有效元素为总容量的四分之一且还存在有效元素,则将容量缩减为原来的一半
            self._resize(self._capacity // 2)
        return ret
 
    def removeFirst(self):
        """
        删除数组首位置的元素
        时间复杂度:O(n)
        :return: 数组首位置的元素
        """
        return self.remove(0)   # 调用remove函数
 
    def removeLast(self):
        """
        删除数组末尾的元素
        时间复杂度:O(1)
        :return: 数组末尾的元素
        """
        return self.remove(self._size - 1)      # 调用remove函数
 
    def removeElement(self, elem):
        """
        删除数组中为elem的元素,如果数组中不存在elem,那么什么都不做。如果存在多个相同的elem,只删除最左边的那个
        时间复杂度:O(n)
        :param elem: 要删除的目标元素
        """
        index = self.find(elem)         # 尝试找到目标元素(最左边的)的索引
        if index != -1:                 # elem在数组中就删除,否则什么都不做
            self.remove(index)          # 调用remove函数
 
    def removeAllElement(self, elem):
        """
        删除数组内所有值为elem的元素,可以用递归来写,这里用的迭代的方法。elem不存在就什么都不做
        :param elem: 要删除的目标元素
        """
        while True:
            index = self.find(elem)     # 循环来找elem,如果还存在就继续删除
            if index != -1:             # 若存在
                self.remove(index)
            else:
                break
 
    def get_Max_index(self):
        """
        获取数组中的最大元素的索引,返回最大元素的索引值,如果有多个最大值,默认返回最左边那个的索引
        时间复杂度: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开始遍历,一直到数组尾部
            if self._data[i] > self._data[max_elem_index]:   # 如果当前索引的值大于最大值索引处元素的值
                max_elem_index = i     # 更新max_elem_index,这样它还是当前最大值的索引
        return max_elem_index     # 遍历完后,将数组的最大值的索引返回
 
    def removeMax(self):
        """
        删除数组中的最大元素,返回最大元素的值,如果有多个最大值,默认值删除最左边那个
        时间复杂度:O(n)
        :return: 最大元素
        """
        return self.remove(self.get_Max_index())   # 直接调用remove函数删除最大值
 
    def get_Min_index(self):
        """
        获取数组中的最小元素的索引,返回最小元素的索引值,如果有多个最小值,默认返回最左边那个的索引
        时间复杂度: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开始遍历,一直到数组尾部
            if self._data[i] < self._data[min_elem_index]:   # 如果当前索引的值小于最小值索引处元素的值
                min_elem_index = i     # 更新min_elem_index,这样它还是当前最小值的索引
        return min_elem_index     # 遍历完后,将数组的最小值的索引返回
 
    def removeMin(self):
        """
        删除数组中的最小元素,返回最小元素的值,如果有多个最小值,默认值删除最左边那个
        时间复杂度: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):
        """对数组元素进行打印"""
        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):
        """
        数组容量放缩至new_capacity,私有成员函数
        :param new_capacity: 新的容量
        """
        new_arr = Arr(new_capacity)         # 建立一个新的数组new_arr,容量为new_capacity
        for i in range(self._size):
            new_arr.addLast(self._data[i])  # 将当前数组的元素按当前顺序全部移动到new_arr中
        self._capacity = new_capacity       # 数组容量变为new_capacity
        self._data = new_arr._data          # 将new_arr._data赋值给self._data,从而完成数组的容量放缩操作

2.列表

  1. 列表是最常用的 Python 数据类型,它可以作为一个方括号内的逗号分隔值出现。
  2. 列表的数据项不需要具有相同的类型
  3. 创建一个列表,只要把逗号分隔的不同的数据项使用方括号括起来即可。如下所示:

创建列表:

list1 = ['Google', 'Runoob', 1997, 2000]
list2 = [1, 2, 3, 4, 5 ]
list3 = ["a", "b", "c", "d"]
list4 = ['red', 'green', 'blue', 'yellow', 'white', 'black']

2.1 访问列表的值

(从前到后)列表索引从 0 开始,第二个索引是 1,依此类推。
(从后到前)索引也可以从尾部开始,最后一个元素的索引为 -1,往前一位为 -2,以此类推。

list = ['Google', 'Runoob', "Zhihu", "Taobao", "Wiki"]
 
# 读取第二位
print ("list[1]: ", list[1])
# 从第二位开始(包含)截取到倒数第二位(不包含)
print ("list[1:-2]: ", list[1:-2])

2.2 更新列表

可以利用赋值来更新,或者后面追加来更新append()

list = ['ni', 'hao', 2020, 2021]
 
print ("第三个元素为 : ", list[2])
list[2] = 2022
print ("更新后的第三个元素为 : ", list[2])
 
list1 = ['Google', 'byte', 'Taobao']
list1.append('Baidu')
print ("更新后的列表 : ", list1)

2.3 删除元素

直接用del语句来删除列表的元素:

list = ['Google', 'soft', 2021, 2022]
print ("原始列表 : ", list)
del list[2]
print ("删除第三个元素 : ", list)

2.4 列表嵌套

>>>a = ['a', 'b', 'c']
>>> n = [1, 2, 3]
>>> x = [a, n]
>>> x
[['a', 'b', 'c'], [1, 2, 3]]
>>> x[0]
['a', 'b', 'c']
>>> x[0][1]
'b'

2.5 列表函数&方法

函数

序号函数
1len(list)
列表元素个数
2max(list)
返回列表元素最大值
3min(list)
返回列表元素最小值
4list(seq)
将元组转换为列表

方法:

序号方法
1list.append(obj) 在列表末尾添加新的对象
2list.count(obj)
统计某个元素在列表中出现的次数
3list.extend(seq)
在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表)
4list.index(obj)
从列表中找出某个值第一个匹配项的索引位置
5list.insert(index, obj)
将对象插入列表
6list.pop([index=-1])
移除列表中的一个元素(默认最后一个元素),并且返回该元素的值
7list.remove(obj)
移除列表中某个值的第一个匹配项
8list.reverse()
反向列表中元素
9list.sort( key=None, reverse=False)
对原列表进行排序
10list.clear()
清空列表
11list.copy()
复制列表

Python列表脚本操作符

列表对 + 和 * 的操作符与字符串相似。+ 号用于组合列表,* 号用于重复列表。
如下所示:

Python 表达式结果描述
len([1, 2, 3])3长度
[1, 2, 3] + [4, 5, 6][1, 2, 3, 4, 5, 6]组合
[‘Hi!’] * 4[‘Hi!’, ‘Hi!’, ‘Hi!’, ‘Hi!’]重复
3 in [1, 2, 3]True元素是否存在于列表中
for x in [1, 2, 3]: print(x, end=" ")1 2 3迭代
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值