7、Python——容器类型-数据结构(什么是列表、元组、字典、集合、哈希表,它们的特点以及它们是怎么组成的)

目录

1、数据结构

1.1、程序设计的基本结构

1.2、4种内置数据结构(容器类型)

2、列表(list)⭐⭐⭐

2.1、什么是列表

2.1.1、特点(1)列表是处理一组有序项目的数据结构

2.1.2、特点(2)列表可以包含任何类型的对象:字符串、数字、其他列表甚至是内建函数

2.1.3、特点(3)列表是可变的数据类型,即这种类型的值是可以被修改的

2.2、列表定义

2.2.1、列表通过方括号中用逗号分割的项目定义,list()括号中是可迭代对象(即可用for循环获取的)

2.2.2、定义空列表

2.3、列表的基本操作

2.3.1、(1)增加 ---- appand

2.3.1、(2)增加 ---- insert

2.3.1、(3)增加 ---- extend

2.3.2、删除(pop、clear、remove、del)

2.3.3、约瑟夫环问题

2.3.4、(1)修改---利用切片,在原来列表的基础上进行改变

2.3.4、(2)修改----负切片(负切片是重新生成一个列表,原来的列表不会改变)

2.3.4、(3)修改(反转)----reverse,是在原有列表的基础上做出修改

2.3.5、列表是可以进行加法和乘法,在原基础上做出改变

2.3.6、约瑟夫环

2.3.7、排序  -- sort ,是对自身进行操作

2.3.8、统计 ----len、count、index

2.3.9、遍历-----enumerate

2.3.10、成员关系

2.3.11、类型转换  list

2.3.12、索引

2.3.13、(1)切片和切片的格式是什么?

2.3.13、(2)切片对象(slice函数)

2.3.14、列表小练习

3、元组  --- tuple

3.1、什么是工厂函数?  ⭐⭐⭐

3.2、元组的定义

3.2.1、定义空元组,以及如果元组中只有一个元素的时候,后边一定要加',',不然()会被认定为结合运算

3.3、如果元组里边有列表,列表里的元素是可以改变的

3.4、统计 --- indext,count

3.5、list和tuple的相同点和不同点

4、字典(dict)⭐⭐⭐

4.1、字典里边可以包含有字典

4.2、key是唯一的,天生去重

4.3、key必须是一个可hash对象(可以理解为不可变数据类型),value可以是任何数据类型

4.4、类型转化 --- 只能和列表里边加上元组进行类型转换

4.5、字典的操作

4.5.1、查看(1)--- dict[key]

4.5.1、查看(2)--- dict.get(key,default),推荐使用get,不会报错,兼容性高

4.5.2、新增和修改

4.5.3、删除 ----dict.pop(key)、dict.popitem()

4.6、字典的合并

4.7、成员关系

4.8、字典的遍历

4.9、字典的底层

5、集合

5.1、集合的定义

5.2、集合的类型转换函数  --- set,里边必须是可迭代对象

5.3、集合的操作

5.3.1、添加 --- add  添加一项;update 添加多项,传入一个可迭代对象

5.3.2、删除  ---  remove,如果不存在会报错;discard,如果不存在不会报错

5.4、集合的运算

6、哈希表

6.1、什么是哈希表

6.2、为什么说哈希表本质就是一个数组?

6.3、哈希表和数组的区别

6.4、哈希表的生成

6.5、键值对和Entry

6.6、哈希冲突

6.6.1、 解决哈希冲突的两种方法:

6.7、哈希表如何读取数据

6.8、哈希表中什么是核心

7、关于这几种表的总结


1、数据结构

1.1、程序设计的基本结构

之前 用户密码验证 时(详看该链接的5.1练习——用户登录),如果一个程序需要能验证100、1000、10000.基于更多用户用户时,我们会需要一个 储存东西的容器 。这些存储大量数据的容器,在Python中称之为 内置数据结构 (Built-in Data Structure)。

1.2、4种内置数据结构(容器类型)

        

2、列表(list)⭐⭐⭐

2.1、什么是列表

列表在底层中是由链表数组构成的

2.1.1、特点(1)列表是处理一组有序项目的数据结构

>>> lst = ["a", 1, 0.5, None, "y"]
>>> lst[4]
'y'
>>> lst[3]  # 这里输出的东西是"None"
>>> lst[2]
0.5
>>> lst[2:3]
[0.5]
>>> lst[2:]
[0.5, None, 'y']
>>> lst[-2:]
[None, 'y']
>>> lst[6]     # 这里是超出了列表本身的最大数量
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range
>>> lst[0:6]
['a', 1, 0.5, None, 'y']
>>> lst[-4:4:-1]    # ⭐这是开始在终点的后边,不会报错,输出一个空列表
[]
>>> lst[:0]    # ⭐制造出一个空的列表
[]

2.1.2、特点(2)列表可以包含任何类型的对象:字符串、数字、其他列表甚至是内建函数

>> lst = ["a", 1, 0.5, None, "y", print]
>>> lst
['a', 1, 0.5, None, 'y', <built-in function print>]
>>> lst = ["a", 1, 0.5, None, "y", print, [1,2]]
>>> lst
['a', 1, 0.5, None, 'y', <built-in function print>, [1, 2]]

2.1.3、特点(3)列表是可变的数据类型,即这种类型的值是可以被修改的

可变和不可变的区别:主要是看在原来内存地址上可不可以修改值;注意:字符串是不可变的数据类型

>>> lst
['a', 1, 0.5, None, 'y', <built-in function print>, [1, 2]]
>>> lst[1]
1
>>> id(lst)
139633755096904
>>> lst[1] = 2
>>> lst
['a', 2, 0.5, None, 'y', <built-in function print>, [1, 2]]
>>> id(lst)
139633755096904

2.2、列表定义

2.2.1、列表通过方括号中用逗号分割的项目定义,list()括号中是可迭代对象(即可用for循环获取的)

>>> lst3
['a', 'b', 'c']
>>> list(range(3))
[0, 1, 2]
>>> lst(123)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'list' object is not callable

2.2.2、定义空列表

>>> lst = []
>>> type(lst)
<class 'list'>
>>> lst2 = list()
>>> lst2
[]

2.3、列表的基本操作

2.3.1、(1)增加 ---- appand

# 增加 --- appand    每次只能在末尾增加一个元素
>>> lst
['a', 2, 0.5, None, 'y', <built-in function print>, [1, 2]]
>>> lst.append('sanchuang')
>>> lst
['a', 2, 0.5, None, 'y', <built-in function print>, [1, 2], 'sanchuang']
>>> lst.append([3,4,5])
>>> lst
['a', 2, 0.5, None, 'y', <built-in function print>, [1, 2], 'sanchuang', [3, 4, 5]]

2.3.1、(2)增加 ---- insert

# 增加 ---insert   在指定下标位置添加元素
>>> lst
['a', 'x']
>>> lst.insert(1,'yy')
>>> lst
['a', 'yy', 'x']

2.3.1、(3)增加 ---- extend

# extend--把可迭代对象(可以用for循环获取的)的每一个值分别添加到列表中
>>> lst
['a', 'yy', 'x']
>>> lst.extend('qwer')
>>> lst
['a', 'yy', 'x', 'q', 'w', 'e', 'r']

2.3.2、删除(pop、clear、remove、del)

>>> lst = ['a', 'b', 'c']
>>> lst.pop()          # 会把删除的元素作为返回结果返回
'c'
>>> lst
['a', 'b']
>>> remove_item = lst.pop()
>>> remove_item
'b'
>>> lst.append('x')
>>> lst.append('y')
>>> lst.append('')
>>> lst
['a', 'x', 'y', '']
>>> lst.pop(3)        # 可以指定下标删除,默认删除最后一个
''
# 清除列表
 >>> lst
  ['u', 'x', 'x', 'x', 'x', 'x']
 >>> lst.clear()
 >>> lst
  []
# remove
# 指定元素删除,删掉找到的第一个,找不到会报错
>>> lst = ["s", "b"]
>>> lst
['s', 'b']
>>> lst.remove("s")
>>> lst
['b']
# del
# 指定关键字删除
# 只要通过下标,切片能切出来,就都可用del删除
 >>> lst
  ['u', 'x']
 >>>
  KeyboardInterrupt
 >>> del lst[1]
 >>> lst
  ['u']
 >>> lst = ["a", "b","c"]
 >>> del lst[1:2]
 >>> lst
  ['a', 'c']

2.3.3、约瑟夫环问题

# method3 约瑟夫环
# 第七个人的时候去掉
member = list(range(1,31))
while len(member) > 16:
    i = 1
    while i < 7:
        member.append(member.pop(0))
        i += 1
    print(member.pop(0))

2.3.4、(1)修改---利用切片,在原来列表的基础上进行改变

# 可以通过下标或切片来进行增加和修改  
# 当切片出来的列表为空的时候,就是在start位置开始插入相应的值
# 当切片出来的列表不为空的时候,则替换查找出来的list元素

# 切片修改,必须要赋值一个可迭代对象
# 下标修改,可以接受任意值
>>> lst
['xx', 'y', 1, 'u', 3]
>>> lst[3] = 't'
>>> lst
['xx', 'y', 1, 't', 3]
>>> lst[1:1]
[]
>>> lst[1:1] = 'qw'  # 这里对应这上面的第二点
>>> lst
['xx', 'q', 'w', 'y', 1, 't', 3]
>>> lst[1:4] = 'abc'  # 这里对应着上面的第三点
>>> lst
['xx', 'a', 'b', 'c', 1, 't', 3]
>>> lst[4:2]
[]
>>> lst[4:2] = 'rrr'
>>> lst
['xx', 'a', 'b', 'c', 'r', 'r', 'r', 1, 't', 3]
>>> lst1 = lst
>>> lst1[0:] = 'abc'
>>> lst1
['a', 'b', 'c']

2.3.4、(2)修改----负切片(负切片是重新生成一个列表,原来的列表不会改变)

>>> lst
['xx', 'q', 'w', 'y', 1, 'u', 3]
>>> id(lst)
140235210426760
>>> hh = lst[::-1]  # 负切片
>>> hh
[3, 'u', 1, 'y', 'w', 'q', 'xx']
>>> id(hh)
140235210426888

2.3.4、(3)修改(反转)----reverse,是在原有列表的基础上做出修改

>>> lst = ["my baby","you","love"]
>>> id(lst)
140235210427336
>>> lst.reverse()
>>> lst
['love', 'you', 'my baby']
>>> id(lst)
140235210427336

2.3.5、列表是可以进行加法和乘法,在原基础上做出改变

>>> [1,2]+[3, 4]
[1, 2, 3, 4]
>>> [1,2]*3
[1, 2, 1, 2, 1, 2]

2.3.6、约瑟夫环

题目:有一条船,船上有30个人,船只能载16个人 ;30个进行编号,从1开始,每数到第七个就下船,最后哪些人下船了

# method1 约瑟夫环  ⭐⭐⭐
member = list(range(1,31))
while len(member) > 16:
    i = 1
    while i < 7:
        member.append(member.pop(0))
        i += 1
    print(member.pop(0),end=', ')

# method2
member = list(range(1, 31))
print(member)
out = 6
for i in range(14):
    if out <= len(member) - 1:
        print(member.pop(out))
        out += 6
    else:
        out = out - len(member)
        print(member.pop(out))
        out += 6

2.3.7、排序  -- sort ,是对自身进行操作

# sort   默认为升序
# 列表中的数据类型必须要一致
>>> lst = [6,1,2,45,655,12]
>>> lst.sort()
>>> lst
[1, 2, 6, 12, 45, 655]
>>> lst.sort(reverse=True)   # 降序排序
>>> lst
[655, 45, 12, 6, 2, 1]

# 字符串按照编码排序  ⭐⭐⭐
>>> lst = ['abc','中国','bd','abd','你好']
>>> lst.sort()
>>> lst
['abc', 'abd', 'bd', '中国', '你好']
>>> ord('a')      # 这是查看ASCII编码
97
>>> ord('中国')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: ord() expected a character, but string of length 2 found
>>> ord('中')
20013
>>> ord('你')
20320

2.3.8、统计 ----len、count、index

>>> len(lst)   # len是统计长度
5
>>> lst
['abc', 'abd', 'bd', '中国', '你好']
>>> lst.count('abc')       # 统计在列表中有多少元素"x"(x为你想要统计的元素)
1
>>> lst.count('a')   #是单独搜索'a'元素,不是一个元素(两个字符以上的)包含有'a'的
0
>>> lst.index('abd')     #  查看列表中第一次出现'xxx'的下标
1
>>> lst.index('ab')      #     没找到会报错
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: 'ab' is not in list

2.3.9、遍历-----enumerate

2.3.10、成员关系

2.3.11、类型转换  list

2.3.12、索引

通过下标访问列表中的元素,下标从0开始计数,可取出一个元素

正索引和负索引

 注意:下标不能越界

>>> lst
[1, 2]
>>> lst[3]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range      # 这就是表示越界的结果

2.3.13、(1)切片和切片的格式是什么?

 注意:起始位置有误时,切出来的结果会是,并不会报错

2.3.13、(2)切片对象(slice函数)

2.3.14、列表小练习

# 题目:

# 列表[2,4,5,3,6,7,9]
# 从键盘接受用户的输入,输入一个整数 10
# 告诉我哪两个数相加等于10 返回下标 1,4  只需要输出一组就行


#解决代码:

# method1
a = [2,4,5,3,6,7,9]
num = 0      # 这是为了限制这个程序只输出一个值
target = int(input("请输入要查找的数值"))
for location1,addend1 in enumerate(a):
    for location2,addend2 in enumerate(a[location1+1:]):
        if addend2 + addend1 == target and num == 0:
            print(f"第一个数的数值为{addend1},下标为{location1}; 第二个数的数值为{addend2},下标为{location2}")
            num = 1
else:
    if num == 0:
        print("没有这样的数")

# method2
a = [2,4,5,3,6,7,9]
num = 0      # 这是为了限制这个程序只输出一个值
target = int(input("请输入要查找的数值"))
num = 0
for i in a:
    if target - i in a and num == 0 :
        print(f"这组数为{i}和{target-i},下标分别为{a.index(i)}、{a.index(target-i)}")
        num = 1
else:
    if num == 0:
        print("没有这组数")

# method3    ⭐⭐⭐最优方法
a = [2,4,5,3,6,7,9]
target = int(input("请输入要查找的数值"))
for i,j in enumerate(a):
    num1 = target - j
    if num1 in a[i+1:]:
        num1_index = a[i+1:].index(num1) + i + 1
        print(f"和为数字{target}的两个数下标为:{i},{num1_index}")
        break

3、元组  --- tuple

元组的特点:1、元组是有序项目集合;2、可以存放任何类型对象;3、是不可变数据类型

3.1、什么是工厂函数?  ⭐⭐⭐

工厂函数就是可以改变数据类型的函数:如,str,list,tuple,int等

3.2、元组的定义

元组通过圆括号中用逗号分割的项目定义

3.2.1、定义空元组,以及如果元组中只有一个元素的时候,后边一定要加',',不然()会被认定为结合运算

>> tu1 = ()
>>> type(tu1)
<class 'tuple'>
>>> tu2 = tuple()
>>> tu2
()
>>> tu2 = tuple({1,2,3})    # 这是类型转换
>>> tu2
(1, 2, 3)
>>> dir(tu2)     # 这是查看元组的属性
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'count', 'index']
>>> tu2.index(3)
2
>>> tu2.count(3)
1
>>> tu3 = (1)   #如果元组中只有一个元素,一定要加',',不然()会被认定为结合运算
>>> type(tu3)
<class 'int'>
>>> tu3 = (1,)
>>> type
<class 'type'>

3.3、如果元组里边有列表,列表里的元素是可以改变的

>>> tu = ('a',[1,2])
>>> tu[1]
[1, 2]
>>> tu[1].append(3)   # 这是list里的追加属性
>>> tu
('a', [1, 2, 3])

3.4、统计 --- indext,count

3.5、list和tuple的相同点和不同点

4、字典(dict)⭐⭐⭐

4.1、字典里边可以包含有字典

>>> d1 = {}
>>> type(d1)
<class 'dict'>
>>> d2 = dict()
>>> d2
{}
>>> d3 = {"apple":10,"banana":7}
>>> d3['apple']
10
>>> d3 = {"root":{"password":"123456","money":1000}}
>>> d3['root']
{'password': '123456', 'money': 1000}
>>> d3 = {"root":{"password":"123456","money":1000},'admin':{'password':'admin123','money':2000}}
>>> d3['root']
{'password': '123456', 'money': 1000}
>>> d3['root']['password']
'123456'

4.2、key是唯一的,天生去重

>>> d3 = {'a':3,'b':4,'a':2}
>>> d3
{'a': 2, 'b': 4}

4.3、key必须是一个可hash对象(可以理解为不可变数据类型),value可以是任何数据类型

>>> d3 = {True:2}
>>> d3
{True: 2}
>>> d3 = {5:2}
>>> d3
{5: 2}
>>> d3 = {[1,2]:2}  # 出错的原因,是因为[1,2]是一个可变数据类型
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

4.4、类型转化 --- 只能和列表里边加上元组进行类型转换

>>> lst = [('a',1), ('b',2)]     # ⭐⭐⭐  元组里边的元素只能为两个
>>> d5 = dict(lst)
>>> d5
{'a': 1, 'b': 2}

4.5、字典的操作

查看、新增、修改、取值

4.5.1、查看(1)--- dict[key]

# 一、dict[key]  #当查看的key不存在就会报错

>>> d3 = {'a':3,'b':4,'c':5}
>>> d3['a']
3
>>> d3['d']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'd'

4.5.1、查看(2)--- dict.get(key,default),推荐使用get,不会报错,兼容性高

# 如果没有key则会返回default,如果有这个值就会返回这个值
>>> d3 = {'a':3,'b':4,'c':5}
>>> d3.get('d',0)
0
>>> print(d3.get('d'))   # 如果没有定义default就会返回None
None
>>> d3.get('a',0)
3

4.5.2、新增和修改

dict[key] = value
# 如果key存在,就是修改
# 如果key不存在,就是新增
>>> d3
{'a': 3, 'b': 4, 'c': 5}
>>> d3['a'] = 8
>>> d3
{'a': 8, 'b': 4, 'c': 5}
>>> d3['d'] = 9
>>> d3
{'a': 8, 'b': 4, 'c': 5, 'd': 9}

4.5.3、删除 ----dict.pop(key)、dict.popitem()

# dict.pop(key)
# dict.popitem()  # ()里不需要东西,删除最后一个,返回一个元组
>>> d3.pop('a')
8
>>> d3
{'b': 4, 'c': 5, 'd': 9}
>>> d3.popitem()
('d', 9)
>>> d3
{'b': 4, 'c': 5}
>>> d4 = {'a':{'x':1}}
>>> d4['a']
{'x': 1}
>>> d4['a'].pop('x')
1
>>> d4
{'a': {}}
for key in list(d):
    if key == "a":
        d.pop(key)
print(d)

# 结果
{'b': 2, 'c': 3}

4.6、字典的合并

# dict1.update(dict2) # 将dict2合并到dict1
# dict(dict,**dict2)  #将dict1和dict2合并,生成一个新字典

# 这是把字典更新
>>> d5 = {'a': 1, 'b': 2}
>>> d6={'c': 4, 'd': 3}
>>> id(d5)
139704415893616
>>> id(d6)
139704415894840
>>> d5.update(d6)
>>> d5
{'a': 1, 'b': 2, 'c': 4, 'd': 3}
>>> id(d5)
139704415893616

# 这是生成一个新字典
>>> d5 = dict(d5,**d6)
>>> d5
{'a': 1, 'b': 2, 'c': 4, 'd': 3}
>>> id(d5)
139704415391816

4.7、成员关系

>>> d5
{'a': 1, 'b': 2}
>>> 'b' in d5      #默认判断字典key
True
>>> 2 in d5
False
>>> d5.values()   # 如果想要看values是否在这里边,可以用dict2.values()
dict_values([1, 2])
>>> 2 in d5.values()
True
>>> d5.keys()     # 判断key
dict_keys(['a', 'b'])

4.8、字典的遍历

>>> d5
{'a': 1, 'b': 2}
>>> for i in d5:
...     print(i)
... 
a
b
>>> for i in d5.items():
...     print(i)
... 
('a', 1)
('b', 2)
>>> for i,j in d5.items():
...     print(f"{i}-->{j}")
... 
a-->1
b-->2

4.9、字典的底层

字典底层使用空闲散列表存储;操作的时候需要对key进行hash值的求取

5、集合

集合的特性:1、集合是无序; 2、可变数据类型 集合可以看作是一个只有key的字典 集合的元素必须是可hash的,集合天生去重

5.1、集合的定义

>>> s1 ={1,2,3}
>>> type(s1)
<class 'set'>

5.2、集合的类型转换函数  --- set,里边必须是可迭代对象

>>> s2 = set([1,2,3,1,1,5,6])
>>> s2
{1, 2, 3, 5, 6}   # 这里是因为集合天生去重

5.3、集合的操作

5.3.1、添加 --- add  添加一项;update 添加多项,传入一个可迭代对象

>>> s1.add(5)
>>> s1
{1, 2, 3, 4, 5}
>>> s1.add(1)  # 这里体现了集合的去重
>>> s1
{1, 2, 3, 4, 5}
>>> s1.update(['a','b'])
>>> s1
{1, 2, 3, 4, 5, 'a', 'b'}

5.3.2、删除  ---  remove,如果不存在会报错;discard,如果不存在不会报错

#  remove,如果不存在会报错,discard不会报错
>>> s1
{1, 2, 3, 4, 5, 'b', 'a'}
>>> s1.remove('a')
>>> s1.remove('x')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'x'
>>> s1
{1, 2, 3, 4, 5, 'b'}
>>> s1.discard(1)
>>> s1.discard(5)
>>> s1
{2, 3, 4, 'b'}

5.4、集合的运算

交集、并集、差集、对称差集

>>> s1 = {1,2,3}
>>> s2 = {2,3,4}
>>> s3 = {2,3,4}
>>> s1 & s2   #交集
{2, 3}
>>> s1 | s2   # 并集
{1, 2, 3, 4}
>>> s1 - s2   # 差集
{1}
>>> s1 ^ s2  #对称差集
{1, 4}

6、哈希表

散列表Hash table,也叫哈希表),是根据(Key)而直接访问在内存存储位置的数据结构。也就是说,它通过计算一个关于键值的函数,将所需查询的数据映射到表中一个位置来访问记录,这加快了查找速度。这个映射函数称做散列函数,存放记录的数组称做散列表

6.1、什么是哈希表

哈希表是一种数据结构,它的本质就是一个数组;它的特点是:可以根据一个key值来直接访问数据,因此查找速度快

hash算法,结果是以空间换时间的概念;把任意长度的输入,变更成固定长度的输出;一种单向加密技术。所谓破解密码就是撞库,简单来说,就是自己创造足够大的密文库,然后用明文转化为的散列值来匹配密文库。

[root@fttsaxf ~]# echo '123'  | md5sum
ba1f2511fc30423bdbb183fe33f3dd0f  -
[root@fttsaxf ~]# echo '123asohgoishgowhnskjnshagiduhsgid'  | md5sum
8d1560c2787e34a96bc6aa0995c139e0  -    #得到的散列值,也就是哈希值
[root@fttsaxf ~]# echo '123asohgoishgowhnskjnshagiduhsgidfasgasherhsadhw'  | md5sum
24cf100bb683b76ca9108a316a04a1ee  -

哈希算法   md5  sha1 sha2 sha256 sha512(linux默认的加密算法,即使用命令'less  /etc/shadow'
后,出现内容中的第一行中'$6'表示的就是sha512)  。主要用于文件的校验加密

为了方便理解,下面给出一个实例

6.2、为什么说哈希表本质就是一个数组?

哈希表在底层可以采用两种方法构成:1、数组+链表  2、数组+二叉树

6.3、哈希表和数组的区别

数组中一般就是存放的单一的数据,而哈希表中存放的是一个键值。

6.4、哈希表的生成

哈希表就是通过将key通过一个散列函数(对应的也就是哈希函数)加工处理之后得到的一个值,这个值就是数据存放的位置。我们可以通过这个key快速找到我们想要的数据

6.5、键值对和Entry

键值对就是key-value,简单来说就是一个值对应另外一个值。比如a对应b,那么a就是key,b就是value。哈希表存放的就是这样的键值对,在哈希表中是通过哈希函数将一个值映射到另外一个值的,所以在哈希表中,a映射到b,a就叫做键值,而b就叫做a的哈希值,也叫做hash值,在JDK中也叫做Entry。

6.6、哈希冲突

6.6.1、 解决哈希冲突的两种方法:

1、开放寻址法   

 如果第2个位置也被占据了,那就看后一个位置是否可用,以此类推,直到找到空位置。

如果一直找不到空的位置怎么办:

一定量的位置被占了的时候就会发生扩容,所以位置不会被占光。

2、拉链法

 张三和李四都要放在“1”这个位置上,但是张三先来的,已经占了这个位置,待在了这个位置上了,那李四呢?解决办法就是链表,这时候这个1的位置存放的不单单是之前的那个Entry了,此时的Entry还额外的保存了一个next指针,这个指针指向数组外的另外一个位置,将李四安排在这里,然后张三那个Entry中的next指针就指向李四的这个位置,也就是保存的这个位置的内存地址,如果还有冲突,那就把又冲突的那个Entry放在一个新位置上,然后李四的Entry中的next指向它,这样就形成了一个链表。
原文链接:https://blog.csdn.net/sinat_33921105/article/details/103344078

6.7、哈希表如何读取数据

 比如我们现在要通过学号102011来查找学生的姓名,怎么操作呢?我们首先通过学号利用哈希函数得出位置1,然后我们就去位置1拿数据啊,拿到这个Entry之后我们得看看这个Entry的key是不是我们的学号102011,一看是101011,什么鬼,一边去,这不是我们要的key啊,然后根据这个Entry的next知道下一给位置,在比较key,好成功找到李四。

6.8、哈希表中什么是核心

哈希函数是核心。

7、关于这几种表的总结

元组(tuple)的特点:1、元组是有序项目集合;2、可以存放任何类型对象;3、是不可变数据类型

列表(list)的特点:1、元组是有序项目集合;2、可以存放任何类型对象;3、是可变数据类型

字典(dict)的特点:1、字典是python种一个键值映射的数据类型;2、字典是无序的;3、字典是可变对象

集合(set)的特点:1、集合是一个无序不重复的数据组合;2、集合可以看作是一个只含有key的字典

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
列表Python 列表底层实现是一个数组结构,数组中的每个元素都是一个指针,指向实际存储的元素对象。因为 Python 列表的长度是可变的,所以在插入或删除元素时,Python 会重新分配内存,将原有的元素拷贝到新的内存中,以实现动态扩容或缩容。 元组Python 元组底层实现与列表类似,也是一个数组结构,但是元组是不可变的,即一旦创建,就不能再改变其元素的值。因此,Python 不需要为元组提供动态扩容或缩容的支持,这使得元组在某些场景下比列表更加高效。 字典Python 字典底层实现是一个哈,哈中的每个元素都包含一个键和一个值。Python 使用哈函数将键转换为哈值,然后使用哈值作为索引,将值存储在哈中。当需要查找一个键对应的值时,Python 使用哈函数将键转换为哈值,然后在哈中查找对应的值。如果存在多个键的哈值相同,Python 会使用链将这些键值对连接在一起,称为哈冲突。 集合Python 集合底层实现是一个哈,类似于字典Python 集合中的每个元素都是一个键,而值则为 None。集合使用哈来存储键,因此集合中的元素是无序的。当需要检查一个元素是否存在于集合中时,Python 使用哈函数将元素转换为哈值,然后在哈中查找对应的键。如果键存在,则说明元素存在于集合中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FanMY_71

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值