学习目标:
1.链表
2.哈希表
链表:
链表是由一系列节点组成的元素集合。每个节点包含两部分,数据域item和指向下一个节点的指针next。通过节点之间的相互连接,终串联成一个链表。
创建节点
class Node:
def __init__(self, item):
self.item = item
self.next = None
a = Node(1)
b = Node(2)
c = Node(3)
a.next = b
b.next = c
print(a.next.next.item)
创建链表
头插法
def create_linklist_head(li):
head = Node(li[0])
for element in li[1:]:
node = Node(element)
node.next = head
head = node
return head
def print_r(lk):
while lk:
print(lk.item, end=',')
lk = lk.next
lk = create_linklist_head([1,2,3])
print_r(lk)
尾插法
def create_linklist_tail(li):
head = Node(li[0])
tail = head
for element in li[1:]:
node = Node(element)
tail.next = node
tail = node
return head
链表的插入和删除
p.next = curNode.next
curNode.next = p
p = curNode.next
curNode.next = curNode.next.next
del p
以上是链表插入和删除的逻辑代码,不过你想要完全将它连接起来,可能要花费一些时间去编写,更重要的是理解,甚至要考虑代码多方面因素。
#节点
class Node(object):
def __init__(self, val, p=0):
self.data = val
self.next = p
# 链表操作
class LinkList(object):
#定义头节点
def __init__(self):
self.head = 0
def __getitem__(self, key):
if self.is_empty():
print("链表为空!")
return
elif key < 0 or key > self.gelength():
print("键入值错误!")
return
else:
return self.getitem(key)
def __setitem__(self, key, value):
if self.is_empty():
print("链表为空!")
return
elif key < 0 or key > self.getlength():
print("键入值错误!")
return
else:
self.delete(key)
return self.insert(key)
#初始化链表
def initlist(self, data):
self.head = Node(data[0])
p = self.head
for i in data[1:]:
node = Node(i)
p.next = node
p = p.next
#获取链表长度
def getlength(self):
p = self.head
length = 0
while p!=0:
length += 1
p = p.next
return length
#判断链表是否为空
def is_empty(self):
if self.getlength() == 0:
return True
else:
return False
def clear(self):
self.head = 0
# 单链表添加操作,尾插入
def append(self, item):
q = Node(item)
if self.head == 0:
self.head = q
else:
p = self.head
while p.next != 0:
p = p.next
p.next = q
#获取节点数据域的值
def getitem(self, index):
if self.is_empty():
print("链表为空!")
return
j = 0
p = self.head
while p.next != 0 and j < index:
p = p.next
j += 1
if j == index:
return p.data
else:
print("对象不存在!")
#链表数据插入操作
def insert(self, index, item):
if self.is_empty() or index < 0 or index > self.getlength():
print('链表为空!')
return
if index == 0:
q = Node(item, self.head)
self.head = q
p = self.head
post = self.head
j = 0
while p.next != 0 and j < index:
post = p
p = p.next
j += 1
if index == j:
post.next = p.next
def index(self, value):
if self.is_empty():
print("链表为空!")
return
p = self.head
i = 0
while p.next != 0 and not p.data==value:
p = p.next
i += 1
if p.data == value:
return i
else:
return -1
双链表
双链表的每个节点有两个指针: -个指向后一个节点,另一个指向前一个节点。
双链表节点的插入
p.next = curNode.next
curNode.next.prior = p
p.prior = curNode
curNode.next = p
双链表节点的删除
p = curNode.next
curNode.next = p.next
p.next.prior = curNode
del p
哈希表
哈希表一个通过哈希函数来计算数据存储位置的数据结构,通常支持
如下操作:
insert(key, value):插入键值对(key,value)
get(key): 如果存在键为key的键值对则返回value,否则返回空值
delete(key): 删除键为key的键值对
直接寻址表
当关键字的全域U比较小时,直接寻址是一种简单而有效的方法。
直接寻址技术缺点:
1.当域U很大时,需要消耗大量内存,很不
实际
2.如果域U很大而实际出现的key很少,则大量空间被浪费
3.无法处理关键字不是数字的情况
哈希
直接寻址表: key为k的元素放到k位置上
改进直接寻址表:哈希(Hashing),分为以下步骤:
1.构建大小为m的寻址表T
2. key为k的元素放到h(k)位置.上
3. h(k)是一个函数,其将域U映射到表T[0,…m-1]
哈希表怎么组成
哈希表(Hash Table,又称为散列表),是一种线性表的存储结构。哈希表由一个直接寻址表和一个哈希函数组成。哈希函数h(k)将元素关键字k作为自变量,返回元素的存储下标。
假设有一个长度为7的哈希表,哈希函数h(k)=k%7。元素集合{14,22,3,5}的存储方式如图。
哈希冲突
由于哈希表的大小是有限的,而要存储的值的总数量是无限的,因此对于任何哈希函数,都会出现两个不同元素映射到同一个位置.上的情况,这种情况叫做哈希冲突。
比如h(k)=k%7, h(0)=h(7)=h(14)=…
解决哈希冲突–开放寻址法
开放寻址法:如果哈希函数返回的位置已经有值,则可以向后探查新的位置来存储这个值。
线性探查:如果位置i被占用,则探查i+1, i+2…
二次探查:如果位置i被占用,则探查i+132,i-12,+2.,2.-…
二度哈希:有n个哈希函数,当使用第1个哈希函数h1发生冲突时,则尝试使用h2,h3,
解决哈希冲突–拉链法
拉链法:哈希表每个位置都连接一个链表,当冲突发生时,冲突的元素将被加到该位置链表的最后。
拉链法
# 创建拉链
class linkList:
class Node:
def __init__(self, item=None):
self.item = item
self.next = None
class LinkListIterator:
def __init__(self, node):
self.node = node
def __next__(self):
if self.node:
cur_node = self.node
self.node = cur_node.next
return cur_node.item
else:
raise StopIteration
def __iter__(self):
return self
def __init__(self, iterable=None):
self.head = None
self.tail = None
if iterable:
self.extend(iterable)
def append(self, obj):
s = LinkList.Node(obj)
if not self.head:
self.head = s
self.tail = s
else:
self.tail.next = s
self.tail = s
def extend(self, iterable):
for obj in iterable:
self.append(obj)
def find(self, obj):
for n in self:
if n == obj:
return True
else:
return False
def __iter__(self):
return self.LinkListIterator(self.head)
def __repr__(self):
return "<<" + ",".join(map(str, self)) + ">>"
class HashTable:
def __init__(self, size=101):
self.size = size
self.T = [linkList() for i in range(size)]
def h(self, k):
return k % self.size
def insert(self, k):
i = self.h(k)
if self.find(k):
print("Duplicated Insert.")
else:
self.T[i].append(k)
def find(self, k):
i = self.h(k)
return self.T[i].find(k)