算法基础之数组理论

2023-11-04

1.前言

这是第一次写技术博客,打算是总结一遍数据结构与算法,并尽量结合Leetcode来提升自己,希望各位朋友多提意见!第一轮是基础总结,涵盖的数据结构和相关算法有数组、栈与队列、链表、递归、二叉树、二叉搜索树、堆、排序算法

2.数组基础定义

官方定义:将元素顺序地存放在一块连续的存储区里,元素之间的顺序关系由它们的存储顺序自然表示。
一句话总结:将数据码成一排进行存放。
索引可以有语义,也可以没有语义
优点:快速查询 —> 最好应用于“索引有语义”的情况
注意:并不是所有有语义的索引都适用,比如身份证号(如13131413415153),不太适合开辟从0到这么大的数的空间,浪费!
Anyway,这里我们主要处理索引没语义的情况下数组的使用。

正式开始前,会先提前列出数组的特点如下:

  1. 占用一段连续的内存空间,支持随机(索引)访问,且时间复杂度为O(1)

  2. 添加元素时间复杂度:O(n)

  3. 删除元素时间复杂度:O(n)

3.数组增删改查

3.1基本功能

这里我们为了构造一个动态数组,定义了一个数组类(即Class Array),并根据不同需求构造不同功能。
这里值得注意的是capacity指的是数组最大容量,而size是数组有效元素的数目。

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

3.2添加元素

一开始想怎么往数组最后加一个元素,实现如下:

def addLast(self, elem):
	if self._size == self._capacity:
	            raise Exception('illegal argument, failed array is already full')
	        self._data[self._size] = e
	        self._size += 1

但是能不能有一个add方法可以往数组中随意位置添加一个元素呢?思路:向数组中添加一个元素,注意数组占用的是一段连续的内存空间,所以在添加元素后,数组还是要保证这个特点的,因此需要将后面的元素都向后挪一个位置,而且要注意要先从尾部开始挪,防止元素之间的覆盖。

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:        # 满了
            raise Exception('illegal argument, failed array is already full')
        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

接下来,addLast和addFirst方法就可以直接调用add方法了。

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方法

3.3查询和修改元素

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
 
    

3.4包含、搜索和删除元素

这里讲一下删除的思路:删除索引为index的元素。index后面的元素都要向前移动一个位置

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
       
        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,如果elem不存在就什么都不做,存在就继续删除
            if index != -1:             # 若存在
                self.remove(index)
            else:
                break

3.5其他

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()))
 

3.6检验

让我们写一段代码来试试我们的方法o不ok。

import numpy as np
np.random.seed(7)
test = 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()

结果如下:

0
10
True
1  0  1  4  3  3  1  4  
Size: 8-----Capacity: 10
1  0  1  4  3  3  1  4  2  
Size: 9-----Capacity: 10
4
1  0  1  10  3  3  1  4  2  
Size: 9-----Capacity: 10
True
7
0  2  6  
Size: 3-----Capacity: 10
1  0  1  3  3  1  4  2  
Size: 8-----Capacity: 10
0  1  3  3  1  4  
Size: 6-----Capacity: 10
0  1  3  3  1  
Size: 5-----Capacity: 10
0  1  1  
Size: 3-----Capacity: 10
0  1  1  8  7  6  4  0  7  0  7  6  3  5  8  8  7  5  0  0  2  8  9  6  4  9  7  3  3  8  3  0  1  
Size: 33-----Capacity: 40
8
1  0  1  8  7  6  4  0  7  0  7  6  3  5  8  8  7  5  0  0  2  8  9  6  4  9  7  3  3  8  3  0  1  
Size: 33-----Capacity: 40

应该是OK了吧。

4.动态数组及其时间复杂度

4.1动态数组的实现

如果已有的数组已经装满了,根据已有的方法,是会抛出异常的,所以我们的思路是:开辟一个两倍容量的数组(这样能保证扩容后的空间跟原来保持一个数量级,性能方面有好处),依次把原数组的数据复制到新数组(capacity加倍,size不变)。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

# 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,从而完成数组的容量放缩操作

那么接下来,我们可以回过头改写原来的add方法。

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

同理,当有效元素个数是总容量的1/2时,为了不浪费剩余容量,我们也可以将容量减少至一半,下面我们对remove方法动手:

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 == 2:   # 如果当前有效元素为总容量的二分之一且还存在有效元素,则将容量缩减为原来的一半
            self._resize(self._capacity // 2)
        return ret

此时,我们才算真正实现了动态数组!

4.2增删改查时间复杂度

But,我们开始考虑一下动态数组的时间复杂度。
注意:一般会考虑最坏情况。

  • 添加操作 : O(n)
    在这里插入图片描述

  • 删除操作 :O(n)
    在这里插入图片描述

  • 修改操作 :
    在这里插入图片描述

  • 查询操作:
    在这里插入图片描述
    总结动态数组时间复杂度分析:
    在这里插入图片描述

4.3动态数组均摊复杂度

但这时候会想到,addLast方法是O(1),只有触发resize方法后才会变成O(n),可是并不适合什么时候都会触发resize来扩容的呀。举个如下例子:
在这里插入图片描述
9次addLast操作,触发resize,从而需要8次转移操作,总共进行了17次基本操作。因此平均每次addLast进行了2次基本操作
推广开来,假设capacity=m,m+1次addLast操作,触发resize,从而需要m次转移操作,总共进行了2m+1次基本操作。因此平均每次addLast进行了2次基本操作
所以,我们可以说addLast的均摊复杂度是O(1),跟我们当前数组有多少个元素没关系。同理对于removeLast一样。
通俗来说,这样算均摊复杂度是比算最坏情况有意义的,因为最坏的情况不是每次都出现。实际考量中,如果一个相对比较耗时的操作(如这里resize)不是经常被触发,它的耗时可以被分摊到其他基本操作上的。

4.4复杂度震荡

这个时候我想到一个比较极端的情况,如果一个数组已经满了,再在尾部加一个元素,触发resize,从而复杂度是O(n),但接着我需要删掉刚刚的元素,这时容量变成原来一半了,又触发resize,从而复杂度又是O(n)。
在这里插入图片描述

可是我们前面才讲过addLast和removeLast的均摊复杂度是O(1)啊,究其原因,原来是我们其实减容减的太着急了。所以我们可以试着等有效元素个数是总容量的1/4时,再去减容

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

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

5.1列表操作时间复杂度

在这里插入图片描述

5.2字典操作时间复杂度

在这里插入图片描述

6.致谢

这是第一次学着去在博客总结自己的学习经历,也希望看过的朋友多多指教!也希望自己能坚持下去!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

算法基础之数组理论 的相关文章

  • 为什么应用程序会在 sys.exit 命令之后显示?

    我正在关注这个教程 http zetcode com tutorials pyqt4 firstprograms http zetcode com tutorials pyqt4 firstprograms 在第一个示例中 我不明白为什么应
  • 通过 Python 与 Windows 控制台应用程序交互

    我在 Windows 上使用 python 2 5 我希望通过 Popen 与控制台进程交互 我目前有一小段代码 p Popen console app exe stdin PIPE stdout PIPE issue command 1
  • 如何配置散景图以具有响应宽度和固定高度

    我使用通过组件功能嵌入的散景 实际上我使用 plot sizing mode scale width 它根据宽度进行缩放并保持纵横比 但我想要一个响应宽度但固定或最大高度 这怎么可能实现呢 有stretch both and scale b
  • 错误只有 size-1 数组可以转换为 Python 标量

    我有这个代码 for a in data X for i in a if not i isdigit x hash i data X column row x row row 1 row 0 column column 1 desired
  • OpenCV Python 删除图像中的某些对象

    我正在使用带有 opencv 和 numpy 的 python 来检测天文中的星星 例如这个1 https i stack imgur com AKwEJ jpg图片 使用模板匹配 我可以用阈值检测星星 单击 2 2 https i sta
  • 使用 python 通过搜索端点从 Spotify API 获取曲目

    因此 我尝试使用 API 的搜索端点进行搜索 从而从 Spotify API 获取曲目 请参阅文档 https developer spotify com documentation web api reference search sea
  • 在一张图中同时绘制两个截面强度

    我有一个形状数组 512 512 看起来像 行 x 列 y 密度 z 数组的数量 0 012825 0 020408 0 022976 0 015938 0 02165 0 024357 0 036332 0 031904 0 025462
  • 如何编写高效的配对算法?

    我需要一种算法的帮助 该算法可以有效地将人们分组 并确保以前的配对不会重复 例如 假设我们有 10 位候选人 candidates 0 1 2 3 4 5 6 7 8 9 并假设我们有一个先前匹配的字典 这样每个键值对即candidate
  • Python 中的二进制相移键控

    我目前正在编写一些代码 以使用音频转换通过激光传输消息 文件 和其他数据 我当前的代码使用 python 中 binascii 模块中的 hexlify 函数将数据转换为二进制 然后为 1 发出一个音调 为 0 发出不同的音调 这在理论上是
  • Python3模拟用另一个函数替换函数

    如何使用 python 中的另一个函数来模拟一个函数 该函数也将提供一个模拟对象 我有类似以下操作的代码 def foo arg1 arg2 r bar arg1 does interesting things 我想替换的实现bar函数 让
  • 打印一个 Jupyter 单元中定义的所有变量

    有没有一种更简单的方法来以漂亮的方式显示单个单元格中定义的所有变量的名称和值 我现在做的方式是这样的 但是当有30个或更多变量时我浪费了很多时间 您可以使用whos http ipython readthedocs io en stable
  • 如何通过facebook-sdk python api获取用户帖子?

    我使用 facebook jssdk 授权我的应用程序读取用户个人资料和用户帖子 FB login function response scope user status user likes user photos user videos
  • 检查对象数组中的多个属性匹配

    我有一个对象数组 它们都是相同的对象类型 并且它们有多个属性 有没有办法返回一个较小的对象数组 其中所有属性都与测试用例 字符串匹配 无论该属性类型是什么 使用列表理解all http docs python org 3 library f
  • Selenium 网页抓取与动态内容和隐藏数据表上的美丽汤

    真的需要这个社区的帮助 我正在使用 Selenium 和 Beautiful Soup 对 Python 中的动态内容进行网页抓取 问题是定价数据表无法解析为 Python 即使使用以下代码 html browser execute scr
  • Python将csv数据导出到文件中

    我有以下运行良好的代码 但我无法修剪数据并将其存储在数据文件中 import nltk tweets love this car this view amazing not looking forward the concert def g
  • 将带有两层分隔符的字符串转换为字典 - python

    给定一个字符串 s x t1 ny t2 nz t3 我想转换成字典 sdic x 1 y 2 z 3 我通过这样做让它工作 sdic dict tuple j split t for j in i for i in s split n F
  • 散景中的时间序列流

    我想在散景中绘制实时时间序列 我只想在每次更新时绘制新的数据点 我怎样才能做到这一点 散景网站上有一个动画情节的示例 但它每次都需要重新绘制整个图片 另外 我正在寻找一个简单的示例 我可以在其中逐点绘制时间序列的实时绘图 散景效果0 11
  • 对 pandas 数据框中的每一列应用函数

    我如何以更多的熊猫方式编写以下函数 def calculate df columns mean self df means for column in df columns columns tolist cleaned data self
  • 获取长度为 n 的所有(n-选择-k)组合

    我怎样才能获得长度的所有组合 按顺序 n从数字列表中 例如 给定列表 1 2 3 4 并设置n 3 我怎样才能得到这些结果 1 2 3 1 2 4 1 3 4 2 3 4 For combinations of all possible l
  • 将笔记本生成的 HTML 片段转换为 LaTeX 和 PDF

    在我的笔记本里有时会有 from IPython display import display HTML display HTML h3 The s is important h3 question of the day 但当我后来将笔记本

随机推荐

  • mysql时间区间效率_对于sql中使用to_timestamp判断时间区间和不使用的效率对比及结论...

    关于日期函数TO TIMESTAMP 拓展 date类型是Oracle常用的日期型变量 时间间隔是秒 两个日期型相减得到是两个时间的间隔 注意单位是 天 timestamp是DATE类型的扩展 可以精确到小数秒 fractional sec
  • 打卡湘大OJ第一天

    1063 输入与输出1 Description 请输入一个非负整数 输出其10进制和16进制 使用A F 的值 中间用逗号隔开 不要输出换行 Sample Input 15 Sample Output 15 F 题解 include
  • 听说你还不会写通讯录?C语言通讯录#存储到文件里去,动态版

    前言 会写的不一定真的懂了 本篇文章结合了B站鹏哥的写作手法 循序渐进推进知识点 一步步教你写代码 非常适合初学者学习 建议反复观看 同时作者我也是一个C语言B站初学者 欢迎一起学习交流 批评指正 家人们 来都来了 动动你们发财的小手 给我
  • git指令

    拉取远程分支 git checkout track origin dev git reset soft a0ad996d7b797745c9bdc93e2de6d1bc30ddce8b 一 Git 常用命令速查 git branch 查看本
  • 如何在十分钟内插入1亿条记录到Oracle数据库?

    这里提供一种方法 使用 APPEND 提示 使得十分钟内插入上亿数据成为可能 Create table create table TMP TEST CHAS LEE f01 VARCHAR2 20 f02 NUMBER 10 not nul
  • XSS-Game level 5

    第五关过滤了
  • Java学完SSM后很迷茫,接下来该学哪些呢?

    没必要跟着别人的学习路线图走 你要清楚你的目的是找工作 写过很多次大学的四年安排 今天这篇专门写给大四即将找工作的同学 一 找什么工作 首先分析自己想干什么 以题注说的是Java为主 那么起码要知道找一个Java开发的工作需要什么能力 基本
  • postgresql 中的COALESCE()函数使用小技巧

    这篇文章主要介绍了postgresql 中的COALESCE 函数使用小技巧 具有很好的参考价值 希望对大家有所帮助 一起跟随小编过来看看吧 场景 存在一个用户白名单表 提供了此用户的用户名和地区信息 判断此用户是否在此白名单表中 如 姓名
  • Spring Boot 获取接口调用者的IP

    需求 我们实现一个登陆功能时 可能会有需要记录登陆者IP的需求 用于系统安全分析或账户来源分析 当然还有更多应用场景 工具类如下 来源于网络 已兼容K8S 代理的情况 import org slf4j Logger import org s
  • 树莓派解决 vim 编辑器中文乱码问题

    目录 1 问题由来 2 乱码问题演示 3 解决方案 4 问题解决 1 问题由来 我们用树莓派做项目的时候经常需要在电脑编写程序代码 然后再把代码移植进树莓派进行运行 我们用电脑编写程序的时候避免不了都会写很多中文注释 当我们把 file c
  • 【BEV Review】论文 Delving into the Devils of Bird’s-eye-view 2022-9 笔记

    背景 一般来说 自动驾驶车辆的视觉传感器 比如摄像头 安装在车身上方或者车内后视镜上 无论哪个位置 摄像头所得到的都是真实世界在透视视图 Perspective View 下的投影 世界坐标系到图像坐标系 这种视图与人类的视觉系统很类似 因
  • 表单数据自动封装到javaBean中

    页面表单数据的自动封装到javaBean中 先定义一个Bean类 package com test public class Bean private String name private Integer sex public Strin
  • AD19铺铜操作

    1 在Keep OUT层沿板子边缘画出板子形状 2 PCB设计界面右上角 设置 PCB Editor General 勾选 铺铜修改后自动重铺 3 铺铜之前 打一些过孔 连接板子上下两层 双层板 并设置为GND网络 右边Properties
  • 复制文件夹所有内容 和 删除整个文件夹的2个函数

    选择自 hycapril 的 Blog 实现一个静态方法将指定文件夹下面的所有内容copy到目标文件夹下面 如果目标文件夹为只读属性就会报错 April 18April2005 In STU public static void CopyD
  • keil4 破解心得

    keil4 破解心得 Obj STM32 FD SDCard MP3 axf error L6047U The size nb 在编译时出现 Obj STM32 FD SDCard MP3 axf error L6047U The size
  • bes2300之环境搭建(一)

    目录 环境搭建 sdk文件结构介绍 编译 烧录 配置烧录选项 选择端口 启动升级 简单使用 环境搭建 安装编译工具链 gcc arm none eabi 4 9 2014q4 20141203 win32 exe make 3 81 exe
  • GPIO工作模式

    参考链接 STM32 STM32F4 GPIO八种模式及工作原理详解 Z小旋 CSDN博客 stm32io口的八种工作模式 GPIO 即通用I O 输入 输出 端口 是STM32可控制的引脚 STM32芯片的GPIO引脚与外部设备连接起来
  • [备忘]域用户登陆出现“此工作站和主域间的信任关系失败”错误解决方法

    症状 登陆域用户 出现错误 此工作站和主域间的信任关系失败 并无法登陆 解决方案 1 使用本地用户登录 更改当前 域 为 工作组 如默认的WORKGROUP等 并输入具有域管理权限的用户名 密码 随后此电脑上的 域 将会被删除 2 重启电脑
  • Flink入门看完这篇文章就够了

    文章目录 第一章 概述 第一节 什么是Flink 第二节 Flink特点 第三节 Flink应用场景 第四节 Flink核心组成 第五节 Flink处理模型 流处理和批处理 第六节 流处理引擎的技术选型 拓展 什么是最多一次 最少一次和仅一
  • 算法基础之数组理论

    算法基础之数组理论 1 前言 2 数组基础定义 3 数组增删改查 3 1基本功能 3 2添加元素 3 3查询和修改元素 3 4包含 搜索和删除元素 3 5其他 3 6检验 4 动态数组及其时间复杂度 4 1动态数组的实现 4 2增删改查时间