数据结构-链表,哈希表

学习目标:

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)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值