数据结构
数据结构是指集合中数据元素之间的关系,主要包含数组、栈、队列、链表、树、散列表、堆、图等种类。
1.数组
是指在内存中连续存储的数据结构,在内存中的分配也是连续的。数组通过下标访问数组。
优点:按照索引查找数组方便,按照索引遍历数组快捷。
缺点:数组的大小确定后无法扩容;添加和删除慢;只能存储一种类型的数据。
1.1直接定义法:
matrix=[0,1,2,3]
#构建维度为[4,3]的矩阵
matrix1 = [[ i+j for i in range(3)] for j in range(4)]
1.2 Numpy法
备注:使用Numpy创建数组时,可以使用a[i,j] 或a[i][j]读取
但是不调用包直接定义数组,只能a[i][j]方式。
import numpy as np
matrix = np.array([1,2,3,4])
matrix1 = np.range(10)
matrix2 = np.linspace(1,4,5)
zeros = np.zeros([3,4])
ones = np.ones([3,4])
2.栈
是一种特殊的线性表,只允许在栈顶进行操作,栈底不允许操作。特点为先进后出,后进先出。可进行出栈和入栈操作。
常用于递归类场景
栈作为一种特殊的数据结构,可通过定义类来实现,类中主要包含实现以下功能,包括入栈push,出栈pop,返回顶部peek,查看栈是否为空isEmpty,构造底层列表[],返回栈的长度,具体表现为如下:
class Stack:
def __init__(self):
self.items = []
def isEmpty(self):
return self.items == []
def push(self,item):
self.items.append(item)
def pop(self):
self.items.pop()
def peek(self):
return self.items[len(self.items)-1]
def size(self):
return len(self.items)
s = Stack()
print(s.isEmpty())
s.push(4)
s.push(5)
s.push('dog')
print(s.peek())
s.push('true')
print(s.size())
s.pop()
print(s.size())
print(s.peek())
3.队列
是一种特殊的线性表,不同于栈,可在一段添加称为入队,在另一端取出称为出队,特点为先进先出。在多线程阻塞队列管理中应用较多
3.1用两个栈实现队列
class Solution:
def __init__(self):
self.stack1 = []
self.stack2 = []
def push(self, node):
l1 = len(self.stack1)
if l1 == 0:
self.stack1.append(node)
if l1 != 0:
for i in range(len(self.stack1)):
self.stack2.append(self.stack1[-1])
self.stack1.pop()
self.stack1.append(node)
for j in range(len(self.stack2)):
self.stack1.append(self.stack2[-1])
self.stack2.pop()
def pop(self):
if len(self.stack1) == 0:
return None
if len(self.stack1) != 0:
r = self.stack1[-1]
self.stack1.pop()
return r
4.链表
链表在物理存储单元上非连续、非顺序,其数据元素逻辑关系通过指针表示。单链表每个节点由数据和指向下一节点的指针两部分构成,双链表在单链表基础上增加了前向指针,指向该前一节点。
优点:不需要连续的存储单元,能高效利用存储资源。
缺点:不能直接范围某节点。只能从头节点开始访问。
适合数据量较小,需要频繁增加和删除的场景
4.1构建链表
class Solution:
def addInList(self,head1,head2 ):
map1 = head1.next
map2 = head2.next
i1 = 0
i2 = 0
while map1 != None:
i1 += 1
t1 = map1
map1 = t1.next
while map2 != None:
i2 += 1
t2 = map2
map2 = t2.next
tmp1 = head1.next
tmp2 = head2.next
s1 = head1.data * 10**int(i1)
s2 = head2.data * 10**int(i2)
while tmp1 !=None:
f1 = tmp1
i1 = i1 - 1
s1 += f1.data*(10**int(i1))
tmp1 = f1.next
while tmp2 != None:
f2 = tmp2
i2 = i2 -1
s2 += f2.data*10**int(i2)
tmp2 = f2.next
sf = s1+s2
return sf
##定义一个链表
class Node(object):
def __init__(self,data):
self.data = data
self.next = None
class SingleLinkedList(object):
def __init__(self):
"""初始化链表"""
self.head = None
def isEmpty(self):
"""判断链表是否为空"""
return self.head is None
def length(self):
"""获取链表长度"""
cur = self.head
count = 0
while cur is not None:
count += 1
cur = cur.next
return count
def add_first(self,data):
"""在链表头插入节点"""
node = Node(data)
node.next = self.head
self.head = node
def add_last(self,data):
"""在链表尾插入结点"""
node = Node(data)
if self.isEmpty():
self.head = Node
else:
cur = self.head
while cur.next is not None:
cur = cur.next
cur.next = node
def insert_node(self,index,data):
"""在链表中插入数据"""
if index < 0 or index > self.length():
return False
if index == 0:
self.add_first(data)
if index == self.length():
self.add_last(data)
else:
cur = self.head
count = 0
while count <=index-1:
cur = cur.next
count+=1
node = Node(data)
node.next = cur.next
cur.next = node
def remove(self,data):
"""在链表中删除数据"""
cur = self.head
pre = None
if self.head == data:
self.head = self.head.next
while cur is not None:
cur = cur.next
if cur.next == data:
t = cur.next
t1 = t.next
cur.next = t1
def search_node_is_exist(self,data):
cur = self.head
while cur is not None:
if cur.data == data:
return True
else:
cur = cur.next
return False
def traversal(self):
"""遍历整个链表"""
cur = self.head
while cur is not None:
print (cur.data)
cur = cur.next
if __name__=='__main__':
List1 = SingleLinkedList()
List2 = SingleLinkedList()
List1.add_first(9)
List1.add_last(3)
List1.add_last(7)
List2.add_first(6)
List2.add_last(3)
List1.traversal()
List2.traversal()
print(List1.head)
a = Solution()
print(a.addInList(List1.head,List2.head))
5.树
有限个节点组成具有层次关系的集合。
每个节点都有0个或多个子节点
没有父节点的节点为根节点
除了根节点,每个节点有且只有一个父节点
除了根节点,每个子节点构成不交叉的树
二叉树是树结构中较为特殊的一种
每个节点最多有两个子树,度最大为2
左子树和右子树是有顺序的,次序不能颠倒
即使某一节点只有一个子树,也要区分左右子树
6.散列表
散列表,又称为哈希表,直接通过关键码和值直接进行访问的数据结构。
散列表中KEY和VALUE的之间的对应关系是通过哈希函数来表示的。通过哈希函数将KEY转化为整数数字,按照数组长度取余,即为数组的下标,在数组这下标中存储VALUE值。
这种方式充分利用了数组查询快速便捷。然而需要添加删除时,这种方式慢。
7.堆
是一中比较特殊的完全二叉树,子节点不大于或不小于父节点值,前者为大顶堆,后者为小顶堆。
8.图
是由有限顶点V和有限边E集合构成。若两个顶点之间存在一条边,则表示这两个顶点相邻。按照连接顶点之间的边是否有方向可分为有向图和无向图。