【Numpy基础知识】在ndarrays上索引

news2024/10/6 8:16:40

在ndarrays上索引

来源:Numpy官网:https://numpy.org/doc/stable/user/basics.html

在这里插入图片描述

文章目录

    • 在ndarrays上索引
      • 导包
        • 【1】基本索引
        • 【2】高级索引
        • 【3】结合高级索引和基本索引
        • 【3】现场访问
        • 【4】展开迭代器索引
        • 【5】为索引数组赋值
        • 【6】处理程序中可变数量的索引

导包

import numpy as np

【1】基本索引

① 单元素索引

单元素索引的工作方式与其他标准 Python 序列完全相同。它从 0 开始,并接受负索引从数组末尾开始索引。

x = np.arange(10)
print(x)
[0 1 2 3 4 5 6 7 8 9]
x[2]
2
x[-2]
8

没有必要将每个维度的索引分隔到其自己的一组方括号中。

x.shape = (2, 5)
print(x)
[[0 1 2 3 4]
 [5 6 7 8 9]]
x[1, 3]
8
x[1, -1]
9

注意,如果索引的多维数组少于维度,则会得到一个子维度数组。例如

print(x[0])
[0 1 2 3 4]

必须注意的是,返回的数组是一个视图,即它不是原始数组的副本,而是指向内存中与原始数组相同的值。

x[0][2]
2

注意 x[0, 2] == x[0][2],尽管第二种情况效率更低,因为在第一个索引之后创建了一个新的临时数组,随后由 2 索引。

② 切片与步长

基本切片将 Python 的基本切片概念扩展到 N 维。

【注意】NumPy 切片创建一个视图,而不是像内置 Python 序列(如字符串、元组和列表)那样创建副本。从大数组中提取一小部分时必须小心,该部分在提取后变得无用,因为提取的一小部分包含对大型原始数组的引用,直到从它派生的所有数组都被垃圾回收后,其内存才会被释放。在这种情况下,建议使用显式 copy()

基本的切片语法是 i:j:k,其中 i 是起始索引,j 是停止索引,k 是步长 (k ≠ 0)

x = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
print(x)
[0 1 2 3 4 5 6 7 8 9]
print(x[1:7:2])
[1 3 5]

负 i 和 - j 被解释为 n + i 和 n + j,其中 n 是相应维度中的元素数。

print(x)
[0 1 2 3 4 5 6 7 8 9]
print(x[-2:10])
[8 9]
print(x[8:10])  ## 等价
[8 9]
print(x[-3:3:-1])
[7 6 5 4]
print(x[7:3:-1])
[7 6 5 4]

:: 与 : 相同,表示沿着此轴选择所有索引

print(x)
[0 1 2 3 4 5 6 7 8 9]
print(x[5:])
[5 6 7 8 9]
print(x[5::])
[5 6 7 8 9]

如果选择元组中的对象数小于 N,则假定 : 对于任何后续维度。例如:

x = np.array([[[1], [2], [3]], [[4], [5], [6]]])
print(x)
[[[1]
  [2]
  [3]]

 [[4]
  [5]
  [6]]]
x.shape
(2, 3, 1)
print(x[1:2])
[[[4]
  [5]
  [6]]]

③ 维度索引工具

x
array([[[1],
        [2],
        [3]],

       [[4],
        [5],
        [6]]])
print(x[..., 0])
[[1 2 3]
 [4 5 6]]

这等价于

x[:, :, 0]
array([[1, 2, 3],
       [4, 5, 6]])

newaxis 对象用于将生成的所选内容的尺寸扩展一个单位长度的维度。【newaxis 是 None 的别名】

x.shape
(2, 3, 1)
x[:, np.newaxis, :, :].shape
(2, 1, 3, 1)
x[:, None, :, :].shape
(2, 1, 3, 1)

这可以方便地组合两个数组,否则需要显式重塑操作。例如:

x = np.arange(5)
print(x)
[0 1 2 3 4]
print(x[:, np.newaxis])
[[0]
 [1]
 [2]
 [3]
 [4]]
print(x[np.newaxis, :])
[[0 1 2 3 4]]
x[:, np.newaxis] + x[np.newaxis, :]
array([[0, 1, 2, 3, 4],
       [1, 2, 3, 4, 5],
       [2, 3, 4, 5, 6],
       [3, 4, 5, 6, 7],
       [4, 5, 6, 7, 8]])

【2】高级索引

高级索引始终返回数据的副本(与返回视图的基本切片相反)).

① 整数数组索引

x = np.arange(10, 1, -1)
print(x)
[10  9  8  7  6  5  4  3  2]
print(x[np.array([3, 3, 1, 8])])
[7 7 9 2]
print(x[np.array([3, 3, -3, 8])])
[7 7 4 2]

使用多维索引数组进行索引往往是更不寻常的用途,但它们是允许的,并且它们对某些问题很有用。我们将从最简单的多维案例开始:

y = np.arange(35).reshape(5, 7)
print(y)
[[ 0  1  2  3  4  5  6]
 [ 7  8  9 10 11 12 13]
 [14 15 16 17 18 19 20]
 [21 22 23 24 25 26 27]
 [28 29 30 31 32 33 34]]
print(y[np.array([0, 2, 4]), np.array([0, 1, 2])])
[ 0 15 30]

结果数组的第一个值为 y[0, 0]下一个值是 y[2, 1],最后一个值是 y[4, 2].

广播机制允许索引数组与其他索引的标量组合。效果是标量值用于索引数组的所有相应值:

print(y)
[[ 0  1  2  3  4  5  6]
 [ 7  8  9 10 11 12 13]
 [14 15 16 17 18 19 20]
 [21 22 23 24 25 26 27]
 [28 29 30 31 32 33 34]]
print(y[np.array([0, 2, 4]), 1])
[ 1 15 29]
x = np.array([[1, 2], [3, 4], [5, 6]])
print(x)
[[1 2]
 [3 4]
 [5 6]]
print(x[[0, 1, 2], [0, 1, 0]])
[1 4 5]
x = np.array([[0, 1, 2],
              [3, 4, 5],
              [6, 7, 8],
              [9, 10, 11]])
print(x)
[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 9 10 11]]
rows = np.array([[0, 0],
                 [3, 3]], dtype=np.intp)
print(rows)
[[0 0]
 [3 3]]
columns = np.array([[0, 2],
                    [0, 2]], dtype=np.intp)
print(columns)
[[0 2]
 [0 2]]
print(x[rows, columns])
[[ 0  2]
 [ 9 11]]

但是,由于上面的索引数组只是重复自己,因此可以使用广播

rows = np.array([0, 3], dtype=np.intp)
print(rows)
[0 3]
columns = np.array([0, 2], dtype=np.intp)
print(columns)
[0 2]
print(rows[:, np.newaxis])
[[0]
 [3]]
print(x[rows[:, np.newaxis], columns])
[[ 0  2]
 [ 9 11]]

这种广播也可以使用ix_ 函数实现

print(x)
[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 9 10 11]]
print(x[np.ix_(rows, columns)])
[[ 0  2]
 [ 9 11]]

注意,如果没有np.ix_调用,将仅选择对角线元素:

print(x[rows, columns])
[ 0 11]

② 布尔数组索引

一个常见的用例是筛选所需的元素值。例如,可能希望从数组中选择所有不是 NaN 的条目:

x = np.array([[1., 2.], [np.nan, 3.], [np.nan, np.nan]])
print(x)
[[ 1.  2.]
 [nan  3.]
 [nan nan]]
print(x[~np.isnan(x)])
[1. 2. 3.]

或者希望为所有负元素添加一个常量:

x = np.array([1., -1., -2., 3])
print(x)
[ 1. -1. -2.  3.]
x[x < 0] += 20
print(x)
[ 1. 19. 18.  3.]
x = np.arange(35).reshape(5, 7)
print(x)
[[ 0  1  2  3  4  5  6]
 [ 7  8  9 10 11 12 13]
 [14 15 16 17 18 19 20]
 [21 22 23 24 25 26 27]
 [28 29 30 31 32 33 34]]
b = x > 20
print(b)
[[False False False False False False False]
 [False False False False False False False]
 [False False False False False False False]
 [ True  True  True  True  True  True  True]
 [ True  True  True  True  True  True  True]]
print(b[:, 5])
[False False False  True  True]
print(x[b[:, 5]])
[[21 22 23 24 25 26 27]
 [28 29 30 31 32 33 34]]

在这里,从索引数组中选择第 4 行和第 5 行并组合成二维数组。

从数组中,选择总和小于或等于 2 的所有行:

x = np.array([[0, 1], [1, 1], [2, 2]])
print(x)
[[0 1]
 [1 1]
 [2 2]]
rowsum = x.sum(-1)
print(rowsum)
[1 2 4]
print(x[rowsum <= 2, :])
[[0 1]
 [1 1]]

使用布尔索引选择所有行,总和为偶数。

x = np.array([[0, 1, 2],
              [3, 4, 5],
              [6, 7, 8],
              [9, 10, 11]])
print(x)
[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 9 10 11]]
rows = (x.sum(-1) % 2) == 0
print(rows)
[False  True False  True]
columns = [0, 2]
print(columns)
[0, 2]
x[np.ix_(rows, columns)]
array([[ 3,  5],
       [ 9, 11]])

如果没有np.ix_调用,则只会选择对角线元素。

使用形状 (2, 3) 的二维布尔数组和四个 True 元素从形状 (2, 3, 5) 的三维数组中选择行,结果为形状 (4, 5):

x = np.arange(30).reshape(2, 3, 5)
x
array([[[ 0,  1,  2,  3,  4],
        [ 5,  6,  7,  8,  9],
        [10, 11, 12, 13, 14]],

       [[15, 16, 17, 18, 19],
        [20, 21, 22, 23, 24],
        [25, 26, 27, 28, 29]]])
b = np.array([[True, True, False], [False, True, True]])
print(b)
[[ True  True False]
 [False  True  True]]
x[b]
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [20, 21, 22, 23, 24],
       [25, 26, 27, 28, 29]])

【3】结合高级索引和基本索引

y = np.arange(35).reshape(5, 7)
print(y)
[[ 0  1  2  3  4  5  6]
 [ 7  8  9 10 11 12 13]
 [14 15 16 17 18 19 20]
 [21 22 23 24 25 26 27]
 [28 29 30 31 32 33 34]]

在最简单的情况下,只有一个高级索引与一个切片组合在一起。例如:

y[np.array([0, 2, 4]), 1:3]
array([[ 1,  2],
       [15, 16],
       [29, 30]])

实际上,切片和索引数组操作是独立的。切片操作提取具有索引 1 和 2 的列(即第 2 列和第 3 列),然后是索引数组操作,该操作提取具有索引 0、2 和 4 的行(即第一、第三和第五行)。这相当于:

y[:, 1:3][np.array([0, 2, 4]), :]
array([[ 1,  2],
       [15, 16],
       [29, 30]])
x = np.array([[0, 1, 2],
              [3, 4, 5],
              [6, 7, 8],
              [9, 10, 11]])
print(x)
[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 9 10 11]]
x[1:2, 1:3]
array([[4, 5]])
x[1:2, [1, 2]]
array([[4, 5]])

切片可以与广播布尔索引结合使用:

x = np.arange(35).reshape(5, 7)
print(x)
[[ 0  1  2  3  4  5  6]
 [ 7  8  9 10 11 12 13]
 [14 15 16 17 18 19 20]
 [21 22 23 24 25 26 27]
 [28 29 30 31 32 33 34]]
b = x > 20
print(b)
[[False False False False False False False]
 [False False False False False False False]
 [False False False False False False False]
 [ True  True  True  True  True  True  True]
 [ True  True  True  True  True  True  True]]
x[b[:, 5], 1:3]
array([[22, 23],
       [29, 30]])

【3】现场访问

x = np.zeros((2, 2), dtype=[('a', np.int32), ('b', np.float64, (3, 3))])
x['a'].shape
(2, 2)
x['a'].dtype
dtype('int32')
x['b'].shape
(2, 2, 3, 3)
x['b'].dtype
dtype('float64')

【4】展开迭代器索引

x.flat 返回一个迭代器,该迭代器将遍历整个数组(采用 C 连续样式,最后一个索引变化最快)。

【5】为索引数组赋值

例如,允许为切片分配常量:

x = np.arange(10)
print(x)
[0 1 2 3 4 5 6 7 8 9]
x[2:7] = 1
print(x)
[0 1 1 1 1 1 1 7 8 9]

或大小合适的数组:

x[2:7] = np.arange(5)
print(x)
[0 1 0 1 2 3 4 7 8 9]

注意,某些操作可能无法像我们天真期望的那样工作。

x = np.arange(0, 50, 10)
print(x)
[ 0 10 20 30 40]
x[np.array([1, 1, 3, 1])] += 1
print(x)
[ 0 11 20 31 40]

人们期望第一个位置将增加 3。事实上,它只会增加 1。原因是从包含 1、1、3、1 值的原始数组(作为临时数组)中提取一个新数组,然后将值 1 添加到临时数组中,然后将临时数组分配回原始数组。因此,x[1] + 1 处的数组值分配给 x[1] 三次,而不是递增 3 次。

【6】处理程序中可变数量的索引

如果向索引提供元组,则元组将被解释为索引列表。例如:

z = np.arange(81).reshape(3, 3, 3, 3)
print(z)
[[[[ 0  1  2]
   [ 3  4  5]
   [ 6  7  8]]

  [[ 9 10 11]
   [12 13 14]
   [15 16 17]]

  [[18 19 20]
   [21 22 23]
   [24 25 26]]]


 [[[27 28 29]
   [30 31 32]
   [33 34 35]]

  [[36 37 38]
   [39 40 41]
   [42 43 44]]

  [[45 46 47]
   [48 49 50]
   [51 52 53]]]


 [[[54 55 56]
   [57 58 59]
   [60 61 62]]

  [[63 64 65]
   [66 67 68]
   [69 70 71]]

  [[72 73 74]
   [75 76 77]
   [78 79 80]]]]
indices = (1, 1, 1, 1)
print(z[indices])
40

因此,可以使用代码构造任意数量的索引的元组,然后在索引中使用这些元组。

indices = (1, 1, 1, slice(0, 2))
print(indices)  ## 和 same as [1, 1, 1, 0:2]
(1, 1, 1, slice(0, 2, None))
print(z[indices])
[39 40]

同样,可以使用 Ellipsis 对象由代码指定省略号:

indices = (1, Ellipsis, 1)  # 等价于 [1, ... ,1]
print(indices)
(1, Ellipsis, 1)
print(z[indices])
[[28 31 34]
 [37 40 43]
 [46 49 52]]

由于元组的特殊处理,它们不会像列表那样自动转换为数组。举个例子:

print(z)
[[[[ 0  1  2]
   [ 3  4  5]
   [ 6  7  8]]

  [[ 9 10 11]
   [12 13 14]
   [15 16 17]]

  [[18 19 20]
   [21 22 23]
   [24 25 26]]]


 [[[27 28 29]
   [30 31 32]
   [33 34 35]]

  [[36 37 38]
   [39 40 41]
   [42 43 44]]

  [[45 46 47]
   [48 49 50]
   [51 52 53]]]


 [[[54 55 56]
   [57 58 59]
   [60 61 62]]

  [[63 64 65]
   [66 67 68]
   [69 70 71]]

  [[72 73 74]
   [75 76 77]
   [78 79 80]]]]
print(z[[1, 1, 1, 1]])
[[[[27 28 29]
   [30 31 32]
   [33 34 35]]

  [[36 37 38]
   [39 40 41]
   [42 43 44]]

  [[45 46 47]
   [48 49 50]
   [51 52 53]]]


 [[[27 28 29]
   [30 31 32]
   [33 34 35]]

  [[36 37 38]
   [39 40 41]
   [42 43 44]]

  [[45 46 47]
   [48 49 50]
   [51 52 53]]]


 [[[27 28 29]
   [30 31 32]
   [33 34 35]]

  [[36 37 38]
   [39 40 41]
   [42 43 44]]

  [[45 46 47]
   [48 49 50]
   [51 52 53]]]


 [[[27 28 29]
   [30 31 32]
   [33 34 35]]

  [[36 37 38]
   [39 40 41]
   [42 43 44]]

  [[45 46 47]
   [48 49 50]
   [51 52 53]]]]
print(z[(1, 1, 1, 1)])
40

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

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

相关文章

Python3 环境搭建

本章节我们将向大家介绍如何在本地搭建 Python3 开发环境。 Python3 可应用于多平台包括 Windows、Linux 和 Mac OS X。 Unix (Solaris, Linux, FreeBSD, AIX, HP/UX, SunOS, IRIX, 等等。)Win 9x/NT/2000Macintosh (Intel, PPC, 68K)OS/2DOS (多个DOS版本)PalmOSNokia 移动手…

浅谈转行Python的看法,分享我的学习方法

今天跟大家聊一下转行Python的看法和经验。本人之前是做Java开发的&#xff0c;后面因为公司需要Python技术&#xff0c;就接触到了Python&#xff0c;我发现Python比Java更加容易理解&#xff0c;简洁&#xff0c;后面随着Python项目的增多干脆就转行做Python开发了。 Python…

LaTeX教程(三)——文档格式排版

文章目录1. 章节目录1.1 生成章节1.2 生成目录2. 交叉引用和脚注2.1 交叉引用2.2 脚注3. 特殊环境3.1 列表3.2 文本对齐3.3 引用环境3.4 代码环境1. 章节目录 1.1 生成章节 写文章或者论文的时候&#xff0c;章节目录可谓是必不可少的&#xff0c;下面我们来聊聊LaTeX怎么处理…

Linux——安装和使用vmtools

实验1 Linux系统初识 一、安装和使用vmtools vmware tools是虚拟机VMware Workstation自带的一款工具&#xff0c;现在介绍ubuntu linux安装VMare tools。它的作用就是使用户可以从物理主机直接往虚拟机里面拖文件。如果不安装它&#xff0c;我们是无法进行虚拟机和物理…

【火电机组、风能、储能】高比例风电电力系统储能运行及配置分析附Matlab代码

​✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法…

第十三章ThreadLocal

文章目录什么是ThreadLocal基本使用常用方法使用ThreadLocal来解决使用sychronized解决ThreadLocal与synchronized的区别运用场景_事务案例场景构建引入事务JDBC中关于事务的操作的api常规解决方案常规方案的弊端ThreadLocal解决方案ThreadLocal方案的好处ThreaLocal的内部结构…

Java堆排序和代码实现详解

堆的定义 堆是计算机科学中一类特殊的数据结构的统称&#xff0c;堆通常可以被看做是一棵完全二叉树的数组对象。 堆的特性 1.它是完全二叉树&#xff0c;除了树的最后一层结点不需要是满的&#xff0c;其它的每一层从左到右都是满的&#xff0c;如果最后一层结点不是满的&…

Hadoop(入门)

一、Hadoop概述 1.1 Hadoop是什么 1&#xff09;Hadoop是一个由Apache基金会所开发的分布式系统基础架构。 2&#xff09;主要解决&#xff0c;海量数据的存储和海量数据的分析计算问题。 3&#xff09;广义上来说&#xff0c;Hadoop通常是指一个更广泛的概念—Hadoop生态圈。…

[Vue3]自定义指令实现组件元素可拖拽移动

实现思路&#xff1a; 元素移动设计思路 1.在光标按下的时刻记录下光标的绝对位置坐标&#xff08;以视窗左上角为原点&#xff09;&#xff08;const {clientX, clientY} evt&#xff09; clientX / clientY 事件属性返回当事件被触发时光标指针相对于浏览器页面当前 body …

flutter系列之:移动端手势的具体使用

文章目录简介赋予widget可以点击的功能会动的组件可删除的组件总结简介 之前我们介绍了GestureDetector的定义和其提供的一些基本的方法&#xff0c;GestureDetector的好处就是可以把任何一个widget都赋予类似button的功能。 今天将会通过几个具体的例子来讲解一下GestureDet…

用ChatGPT写一段嵌入式代码

已剪辑自: https://mp.weixin.qq.com/s/uKkUwXx32LPkUYQK44z1lw 废话不多说&#xff0c;开整&#xff01; ChatGPT: Optimizing Language Models for Dialogue&#xff0c;即优化对话的语言模型&#xff0c;它以对话的方式进行交互。对话形式使ChatGPT能够回答后续问题&#…

性能测试---LoadRunner

目录 1.LoadRunner对比Jmeter的优势 2.LoadRunner三个组件之间的关系 3.学习VUG的使用 3.1创建性能测试脚本并进行录制 第一步:打开VUG,创建一个新的性能测试的脚本 第二步:对新建的脚本进行设置 第三步:启动WebTours服务 第四步:回到VUG中,点击录制按钮并设置录制选项…

学习编程的五个关键点!你需要get它,并运用!

总体来说&#xff0c;学习如何编程是一件较难的事情。我最近发现大学里的计算机课程和各种编程训练营错过了编程的一些重要因素&#xff0c;对新手的教学用了不太恰当的方法。于是&#xff0c;我准备分享一个成功的编程课程应该具备的五大基本支柱。 菜鸟的目标是掌握编程的基…

form表单发送put、delete、patch请求的实现过程

关于发送put、delete、patch请求底层实现过程 对于put这些请求&#xff0c;我们无法直接通过form表单发送&#xff0c;form表单仅支持get和post请求&#xff1b; 虽然我们无法直接通过form表单发送这些请求&#xff0c;但我们可以以form表单为载体做二次请求&#xff1a;使用f…

[附源码]计算机毕业设计Node.js宠物商店管理系统(程序+LW)

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…

48数据流中的中位数 49表达式 50两数之和

48数据流中的中位数 第一次没看到要求排序&#xff0c;还以为题目答案写错了&#xff0c;用排序的内置函数也正好是nlogn import java.util.ArrayList;public class Solution {ArrayList<Integer> list new ArrayList<>();public void Insert(Integer num) {list…

小满nestjs(第二十七章 nestjs typeOrm关系)

在我们开始的过程中&#xff0c;肯定不会把数据存在一个表里面&#xff0c;我们会进行分表&#xff0c;把数据分开存&#xff0c;然后通过关联关系&#xff0c;联合查询。 typeOrm 文档 一对一 | TypeORM 中文文档 前端代码还是复用上一章的 增加了一个添加Tag <template…

腾讯安全联合发布《2022游戏安全白皮书》:外挂对抗仍然激烈

2022年以来&#xff0c;各类游戏安全事件的发生给不断影响着游戏生态的健康发展。同时&#xff0c;随着游戏行业数字化进程的加快&#xff0c;以及游戏全球化布局的不断推进&#xff0c;游戏厂商对于游戏安全的投入越来越大&#xff0c;掌握最新的行业安全态势有利于其安全防护…

外汇天眼:WiKiEXPO亮相香港亚洲博览馆,史上最强大咖阵容坐镇

凛冬已至&#xff0c;在这个寒冷的冬天&#xff0c;WikiGlobal将于2022年12月16日至17日早9:00--晚18:00在香港的亚洲国际博览馆举办为期两天的“Wiki Finance EXPO Asia 2022”。目前展会已拉开帷幕。  此次展会展厅面积高达5000多平方米&#xff0c;经过WiKiEXPO科学的规划和…

【数据结构】线性表之单链表

目录 一、链表的概念 1、概念 2、分类 3、重点 二、单链表模拟实现 1、准备 2、头插法 3、尾插法 4、指定下标插入 5、遍历 6、删除第一次出现的元素key 7、删除所有的key 8、双指针删除所有的key 一、链表的概念 1、概念 是一种物理存储结构上非连续的存储结构&a…