数据结构是指相互之间存在着一种或多种关系的数据元素的集合和该集合中数据元素之间的关系的组成。python
数据结构就是设计数据以何种方式存储在计算机中,列表、字典等都算是数据结构。linux
程序=数据结构+算法,数据结构属于静态的部分,算法的调用为动态部分算法
根据逻辑结构划分:数据库
python中的列表和其余语言中的数组很类似,区别为:编程
append操做会不会使速度变慢?数组
老是能听到一个词 堆栈 ,堆(heap)和栈(stack)是两个东西,传统的编程语言中把内存分为两个地方,堆空间和栈空间,堆存储的是一些动态生成的对象,与数据结构中的堆是不一样的,栈空间由系统调用,存放函数的参数值,局部变量的值。
应该是早年间翻译的问题,通常听到堆栈指的就是栈。安全
#栈的python实现 class Stack: def __init__(self,size): self.size=size self.top = 0 self.lst=[] def push(self,a): if self.top = self.size: raise StackFullError("stackoverflow") self.lst.insert(self.top,a) self.top+=1 def pop(self): if self.top = 0: raise StackEmptyError() b = self.list[self.top] self.lst.pop(self.top) returm b
def brace_match(s): stack = [] d ={'(':')','[':']','{':'}'} for ch in s: if ch in {'(','[','{'}: stack.append(ch) elif len(stack)==0: print('多了%s' %ch) return False elif d[stack[-1]] == ch: stack.pop() else: print('%s不匹配'%ch) if len(stack)==0: return True else: print("未匹配") return False
队列是一个数据集合,仅容许在列表的一端插入,另外一端删除。数据结构
因为数组定长,不能继续添加数据,若是是列表,出队的操做就会出现空位,因此想办法让数组变成一个圆环。app
class queue: def __init__(self, capacity = 10): self.capacity = capacity self.size = 0 self.front = 0 self.rear = 0 self.array = [0]*capacity def is_empty(self): return 0 == self.size def is_full(self): return self.size == self.capacity def enqueue(self, element): if self.is_full(): raise Exception('queue is full') self.array[self.rear] = element self.size += 1 self.rear = (self.rear + 1) % self.capacity def dequeue(self): if self.is_empty(): raise Exception('queue is empty') self.size -= 1 self.front = (self.front + 1) % self.capacity def get_front(self): return self.array[self.front]
class queue: def __init__(self,size): self.a = [] self.b = [] self.size = size def popleft(self): if not self.b and self.b is None: el = self.b.pop(-1) self.append(el) self.a.pop(-1) else: raise Exception("empty") def append(self,item): if self.b<self.size: self.b.append[item] else: raise Exception("FUll")
import queue #涉及线程安全用queue from collections import deque #经常使用解题的用deque q = deque() #是一种双向队列,popleft出队 #模拟linux命令 head和tail,假如是tail 5 deque(open('a.text','r',encooding='utf8'),5) #创建一个定长的队列,当队列满了以后,就会删除第一行,继续添加
链表就是非顺序表,与队列和栈对应。编程语言
链表中每个元素都是一个对象,每一个对象称为一个节点,包含有数据域key和指向下一个节点的next,经过各个节点之间的相互链接,最终串联成一个链表。
头节点为空也是为了表示空链表,也叫作带空节点的链表,头节点也能够记录链表的长度
class Node(object): def __init__(self,item): self.data=data self.next=None #eg a=Node(1) b=Node(2) c=Node(3) a.next=b b.next=c #链表的最后一个节点的next就为None
class LinkList: def __init___(self,li,method='tail'): self.head = None self.tail = None if method == 'head': self.create_linklist_head(li) if method == 'tail' self.create_linklist_tail(li) else: rais ValueError('unsupport') #头插法 def create_linklist_head(self,li): self.head = Node(0) for v in li: n = Node(v) n.next = self.head.next #当插入下一个元素时,应该与下一个节点链接后再跟头节点链接 self.head.next = n self.head.data += 1 #尾插法 def create_linlist_tail(self,li): #不断更新尾巴 self.head = Node(0) self.tail = self.head for v in li: p = Node(v) self.tail.next = p self.tail = p self.head.data += 1 #链表的遍历输出 def traverse_linlist(self): p = self.head.next while p: yield p.data p = p.next
#p表示待插入节点,curNode表示当前节点 p.next = curNode.next #不能当前链接直接断开 curNode,next = p
p = curNode.next curNode.next = p.next del p #不写也同样,引用计数,python的内存回收机制
双链表中每一个节点有两个指针:一个指向后面节点、一个指向前面节点。
节点定义:
class Node(object): def __init__(self, item=None): self.item = item self.next = None self.prior = None
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
链表与列表相比
哈希表就是直接寻址表的改进。当关键字的全域U比较小时,直接寻址是一种简单有效的方法。
哈希表是一个经过哈希函数计算数据存储位置的线性表的存储结构,又叫作散列表。
h(k)= k mod m
h(k) = floor(m(KA mod 1)) 0<A<1
class HashTable: def __init__(self): self.size=11 self.slots=[None]*self.size self.data=[None]*self.size def hash_function(self,key,size): return key%size def rehash(self,old_hash,size): return (old_hash+1)%size def put(self,key,data): hash_value=self.hash_function(key,len(self.slots)) if self.slots[hash_value]==None: self.slots[hash_value]=key self.data[hash_value]=data else: next_slot=self.rehash(hash_value,len(self.slots)) while self.slots[next_slot]!=None and\ self.slots[next_slot]!=key: next_slot=self.rehash(next_slot,len(self.slots)) if self.slots[next_slot]==None: self.slots[next_slot]=key self.data[next_slot]=data else: self.data[next_slot]=data def get(self,key): start_slot=self.hash_function(key,len(self.slots)) data=None stop=False found=False position=start_slot while self.slots[position]!=None and not found and not stop: if self.slots[position]==key: found=True data=self.data[position] else: position=self.rehash(position,len(self.slots)) if position==start_slot: stop=True return data def __getitem__(self,key): return self.get(key) def __setitem__(self,key,data): self.put(key,data)
因为哈希表的大小是有限的,而要存储信息的数量是无限的,所以,对于任何哈希函数,都会出现两个元素映射到同一个位置的状况,这种状况就叫作哈希冲突。
解决哈希冲突的方法:
开放寻址法:若是哈希函数返回的位置已经有值,则能够向后探查新的位置来储存这个值。
p+1,p+2....
。p+1**2,p-1**2,p+2**2
。dic = {'name':'cui'} #能够认为是h('name')=1,则哈希表为[None,'cui']
在堆排序时曾经介绍了什么是二叉树,当时是用列表来实现的,可是二叉树可能出现空值,浪费空间,因此使用相似链表的存储结构。
class BiTreeNode: def __init__(self,data): self.data=data self.lchild=None self.rchild=Node
二叉树的遍历有两类四种:
#前序遍历,root为根节点 def pre_order(root): if root: print(root.data,end = '') pre_order(root.lchild) pre_order(root.rchild) #中序遍历,若是lchild没值则出栈 def in_order(root): if root: pre_order(root.lchild) print(root.data,end = '') pre_order(root.rchild) #后序遍历,若是rchild没值则出栈 def post_order(root): if root: pre_order(root.lchild) pre_order(root.rchild) print(root.data,end = '')
#根据队列实现 def level_order(root): q=deque() q.append(root) while(len(q)>0): x=q.popleft() print(x.data,end='') if x.lchild(): q.append(x.lchild) if x.rchild(): q.append(x.rchild)
二叉搜索树,也叫二叉排序树,它要求每个节点左子树的节点都比它小,右子树的节点都比他大。
class BST: def __init__(self): self.root=None #空不是根节点 而是None def insert(self,key): if not self.root: self.root = BiTreeNode(key) else: p=self.root while p: if key < p.data: #分为左子树是否为空的状况 if p.lchild: #左子树有节点就在左子树继续查找,不然就插入左节点的位置 p = p.lchild else: p.lchild = BiTreeNode(key) elif key > p.data: if p.rchild: p = p.rchild else: p.lchild = BiTreeNode(key) break else: break
def query(self,key): p = self.root while p : if key < p.data: p = p.lchild elif key >p.data: p=p.rchild else: return True return False
删除有三种状况:
平均状况下,二叉搜索时的时间复杂度为O(logn),可是二叉搜索树可能会出现偏斜的状况,须要采用随机打乱的方法,因此这时候采用AVL树(自动平衡树)。
相关知识点:
AVL树:AVL树是一棵自平衡的二叉搜索树,它具备如下性质:
插入一个节点可能会形成AVL树的不平衡,能够经过旋转操做来修正。
插入一个节点后,只有从插入节点到根节点的路径上的节点的平衡可能被改变,须要找到第一个平衡条件的节点,称之为K,K的两棵子树高度差确定为2.
不平衡的出现有四种状况:
B-Tree是一种自平衡的多路搜索树,B-Tree存储在硬盘里,用于数据库的索引。