我们有的basic:① 基本数据类型:int,float,str,bool (python 多装了 list,tuple, set, dict ,且str 也与C++ 中不同,但大作用上无差别)
②三种控制流语句(顺序,多条件分支,迭代) #组织语句作用,本身并不实施处理(:计算和存储)
③赋值语句:求一个表达式的值(计算)并赋给一个变量(存储)
④ 自定义 class 和 function
复杂度:
存储空间来衡量空间复杂度的难点:问题本身描述(自身数据规模) +算法占用
算法运行速度 ≠ 时间复杂性
算法运行速度还与数据规模、运行环境、使用的程序语言等因素有关
ADT(抽象资料类型):利用基本组件,构建的特定类别的资料组装结构(数学模型)
接口:函数名,参数,return值
stack:mystack.push(item),mystack.pop() ,mystack.peek()
queue:
双头:
链构成的列表:
1.UnorderedList:
class UnorderedList: ''' 无序链表插入和删除速度快,保留原有的物理顺序,更符合日常离散的需要 ''' def __init__(self): self.head =None#head是指地址 def add(self,item): '''add 是加在开头''' temp =Node(item) temp.setNext(self.head)#原来的头(地址)现在是第二个 self.head =temp def size(self): '''从链条头head开始遍历到表尾同时用变量累加经过的节点个数。 复杂度O(n)''' current = self.head count = 0 while current != None: count = count +1 current = current.getNext() return count def search(self,item): '''O(n)''' current =self.head found = False while current != None and not found: if current.getData() == item: found = True else: current =current.getNext() return found def remove(self,item): '''because we are a single list''' current =self.head previous = None found = False while not found: if current.getData() == item: found = True else: previous =current current = current.getNext() if previous == None: self.head =current.getNext() else: previous.setNext(current.getNext()) class Node: ''' 这是链表的基准:节点 ''' def __init__(self,initdata): self.data = initdata self.next = None def getData(self): return self.data def getNext(self): return self.next def setData(self,newdata): self.data =newdata def setNext(self,newnext): self.next = newnext
查找:比较对比次数
- 无序表的 sequentialSearch function(alist,item)
- 有序表的 binarySearch function(alist,item)
- 散列 (hashtable): hashfunction 求余数, rehash 防冲突
- 但散列不能因为构造它(存储)而太耗时间,所以根据不同的数据类型,有不同的求余数前的准备活动
- 应对冲突主要是:开放定址--需要大量的空间资源 和 链法
0.先验知识: 无序表:O(n) 找到item ,avg:n/2, wrong: n, best:1 找不到item , n 有序表:O(logn) # finding or not finding but + 排序的开销 散列: 1.size(决定槽数) 2.slot--存key值。 3.为了防止rehash , 可以用开放定址 or 链来存储 1.选择原则: 有序表or无序表:如果一次排序后可以进行多次查找,那么排序的开销就可以摊薄。但如果数据集经常变动,查找次数相对较少,那么可能还是直接用无序表加上顺序查找更快 hash:如果散列函数设计太过复杂,去花费大量的计算资源计算槽号(还不如简单地进行顺序查找或者二分查找)。 散列函数不能成为存储过程和查找过程的计算负担 2.代码 def sequentialSearch(alist, item): """ 无序表的顺序查找法 O(n) 找到:avg:n/2 ,wrong:n , 找不到:n :param alist: :param item: :return: bool found """ pos = 0 found = False while pos <len(alist) and not found: if alist[pos] == item: #值相等 found = True else: pos +=1 return found def binarySearch(alist,item):#递归版本 if len(alist) == 0: #这里不用1是因为最后剩偶数列 return False midpoint = len(alist)//2 if alist[midpoint] == item: return True else: if alist[midpoint] < item: binarySearch(alist[0:midpoint], item) # midpoint 不用包含 else: # 再右半个区间 binarySearch(alist[midpoint + 1::], item)
class Node: """ 这是链表的基准:节点 """ def __init__(self, initdata=None): self.data = initdata self.next = None class HashtableNode: """ 核心板块:取余数(各种hashfunciton,rehash....因为是链所以之后有空在补吧) size:素数 因为本章用的是链所以负载因子....后面有空完善这章时再补吧。 """ def __init__(self, size=None): # 这里size 如果怕忘了设成个默认值素数也是可以的。 # 创建空列表作为哈希表,列表每个元素都是node类型 self.size = size self.slots = [Node()] * size def hash_function(self, key): return key % self.size def hash_function_folding(self, tell_num): """针对手机号,ID Card 这种 默认(input:数字)是直接当做key """ key = list(map(int, str(tell_num))) temp = [sum(key[0:3]), sum(key[3:7]), sum(key[7:11])] # list[]切片 取左不取右 newkey = sum(temp) # self.hash_function(self, newkey) return newkey % self.size def hash_function_str(self,astring): # 针对字符串 sum =0 for pos in range(len(astring)): sum = sum + ord(astring[pos]) return sum % self.size def hashfunction_flx(astring, tablesize): # 针对回文词 total = 0 for pos in range(len(astring)): total = total + ord(astring[pos]) * (pos + 1) # pos+1 权重因子 因pos 从0开始取 return total % tablesize def put(self, key): """ 如果slot 1 还没有就直接做链条头, 如果有找到下个空位扔进去 """ hash_value = self.hash_function(key) # 先求余数 if self.slots[hash_value].data is None: #这里Node of size=3 的起点为none的话 self.slots[hash_value].data = key #余数3 的第一个数为 (key =36:tiger) # 如果已被占据,就在以【哈希表中下标为哈希值的位置 size=3】为起点的链表中顺次检查,直到检查到空位置 else: temp = Node(key) # (key =14:dog) p = self.slots[hash_value] # 向后逐个检查 while p.next is not None: # slot 3号槽的链 ,36,47,25 p = p.next # p=36,true ,p=47,true, p=25 false ,不执行了 ,p.next 现在是接着25的none p.next = temp def get(self, key): hash_value = self.hash_function(key) #把36翻译成 size = 3, 看slot 3 的Node中有没有36 if self.slots[hash_value].data == key: #先看链的起点是不是,不是顺着链爬一遍 return True else: p = self.slots[hash_value] # p存储链表头,爬链吧 while p is not None and p.data is not key: p = p.next # 退出了上方循环后,还没有到链表的末尾,说明已找到 if p != None and p.data == key: return True # 整个链表都未找到,说明整个哈希表里没有存储key的节点 return False
排序:比较交换次数
- 冒泡、搜索
- 插入、谢尔
- (递归)归并,快速