算法结构
简单的算法结构:
1.有0~~1000的a/b/c三个值 a+b+c=1000 且a的平方+b的平方=c*c,求a,b,c
# 有0~~1000的a/b/c三个值 a+b+c=1000 且a的平方+b的平方=c*c,求a,b,c
def qiuzhi():
for a in range(1001):
for b in range(1001):
c=1000-a-b
if a*a+b*b==c*c:
print(a,b,c)
qiuzhi()
2.鸡兔同笼 35个头 94只脚 求鸡兔
# 鸡兔同笼 35个头 94只脚 求鸡兔
def jitu(h = 35, t = 94):
ji = 0
tu= 35
while(ji <= h):
if ji*2+tu*4 == t:
print("ji:",ji)
print("tu:",tu)
break
else:
ji = ji+1
tu = tu-1
jitu()
3.求指定数字以内的所有素数
# 求指定数字以内的所有素数
def shulie(num):
arr=[]
for item in range(2,num+1):
for item1 in range(2,item):
if item%item1==0:
break
else:
arr.append(item)
print(arr)
shulie(100)
4.求指定数字个数的斐波那契数列
#第三个等于前两个之和(传统思维,方法一)
def feifei(num):
lis =[]
for i in range(num):
if i ==0 or i ==1:
lis.append(1)
else:
lis.append(lis[i-2]+lis[i-1])
print(lis)
feifei(10)
# while循环(方法二)
def feibonaqi(num):
a=0
b=1
c=0
arr=[]
while c<num:
arr.append(b)
a,b=b,a+b
c+=1
print(arr)
feibonaqi(10)
# yeild 生成器思想:将函数的返回值变成一个可迭代对象(方法三)
def bianxing(num):
a,b=0,1
c=0
while c<num:
yield b
a,b=b,a+b
c+=1
print(list(bianxing(10)))
#递归思想(方法四)
def feibo(num):
def digui(n):
if n<=1:
return 1
else:
return digui(n-1)+digui(n-2)
for i in range(num):
print(digui(i))
feibo(10)
算法的五大特性:
- 有穷性 算法的有穷性是指算法必须能在执行有限个步骤后终止
- 确切性 算法的每一个步骤必须有确切的定义
- 输入项 一个算法有零个或多个输入项,以刻画运算对象的初始情况,所谓的0个输入是指算法本身定出了初始条件
- 输出项 一个算法有一个或多个输出项
- 可行性
如何衡量算法的优劣性
- 时间
- 空间(内存)
- 时间复杂度(程序运行的步骤)
- 顺序结构(加法法则)
- 循环结构(乘法法则)
- 分支结构(算最大可能性的步骤)
- 大O计数法(近似值【量级最大的函数值】)
- 所消耗的时间从小到大
-
O(1)<O(logn)<O(n)<O(nlogn)<O(n2)<O(n3)<O(2n)<O(n!)<O(nn)
-
- 空间复杂度
- 空间复杂度是对一个算法在运行过程中临时占用内存空间大小的量度
- 递归算法的空间复杂度=递归深度N*每次递归所要的辅助空间
模块
timeit模块 判断程序的运行效率
迭代对象
字符串、列表、字典、集合都是可迭代对象,都可以进行循环
from collections import Iterable(迭代对象) //python内置模块
class diedai:
def __init__(self):
self.xxxx
self.xxxx
def __iter__(self):
return self
def __next__(self):
xxxxxxx(写上逻辑)
return
aa=diedai()
aa.__next__()
#迭代器 iter 函数必须返回 self 调用 __next__ 函数来进行迭代
生成器:(快速生成迭代器)
yeild:协程(协助执行)
#快速生成器
aa=((i for i in range(10)))
print(next(aa))
#这种写法不占空间,用的时候动态计算
#[i for i in range(10)]这个是推导式,两个比较像不要搞混
#生成器
def fibonacci(n):
a,b=0,1
c=0
while c<n:
yield b
a,b=a,a+b
c+=1
#yield的另一种用法:协程(程序运行时碰到yield就暂停)
def aa():
while True:
yield
print("我是aa函数")
def bb():
while True:
yield
print("我是bb函数")
one=aa()
two=bb()
while True:
next(one)
next(two)
数据结构:
数据结构是计算机存储、组织数据的一种方式,数据结构是指互相之间存在一种或多种特定关系的数据元素的集合。通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率,数据结构往往同高效的检索算法和索引技术有关
算法和数据结构的区别
- 数据结构知识静态的描述了数据元素之间的关系
- 高效的程序需要在数据结构的基础上设计和选择算法
- 程序=数据结构+算法
抽象数据类型
抽象数据类型是以个实现包括存储数据元素的存储结构以及实现基本操作的算法
最常用的数据操作有五种:
- 插入
- 删除
- 修改
- 查找
- 排序
python中list就是一种采用分离式技术实现的动态顺序表:
扩充策略:
- 空的时候8位 满了之后*4 直到50000之后乘1
顺序表的两种基本形式
- 按顺序存储数据
- 顺序表的外置形式(按顺序储存数据的地址)
链表:
链条形式:单向不循环链表、单向循环链表、
链表和顺序表都是线性表
-
单向不循环链表
#用面向对象的方式、单向不循环链表的思想创建一个类似列表的数据类型
class error(Exception): #继承Python异常类
def init(self,msg):
super(error,self).init()
self.msg=msg
def str(self):
return self.msg #抛出异常class Node: #创建节点 def __init__(self,item=None): self.ele=item self.next=None class mylist: def __init__(self,node=None): self.head=node #初始化头部 self.next=None #下一个地址为空 self.pos=0 def empty(self): #判断是否为空 return self.head==None def add(self,item): #从开始添加数据 node=Node(item) node.next=self.head #判断有无数据 如果有放到头部 没有直接添加 self.head=node def length(self): #计算长度 cursor=self.head num=0 while cursor != None: cursor=cursor.next num+=1 return num def append(self,item): #在最后添加数据 node = Node(item) if self.empty(): self.head=node else: cursor=self.head while cursor.next != None: cursor=cursor.next cursor.next=node def getEle(self,index): #获取输入下标的元素 if index<0 or index>self.length()-1: raise error("输入的下标超出范围!") else: num=0 cursor=self.head while num<index: cursor=cursor.next num+=1 return cursor.ele def getIndex(self,item): #获取输入元素的下标 node=Node(item) num=0 cursor=self.head while num<self.length(): if cursor.ele == node.ele: return num else: cursor=cursor.next num+=1 return -1 def insert(self,index,item): #在输入的下表位置添加元素 node = Node(item) if index<0 or index>self.length(): raise error("输入的下标超出范围!") else: if index==1: self.add(item) elif index==self.length(): self.append(item) else: num=0 cursor=self.head while num<index-1: cursor=cursor.next num+=1 node.next = cursor.next cursor.next = node def pop(self): #删除最后一个元素 if self.empty(): return None else: if self.length()==1: ele=self.head.ele self.head=None return ele cursor=self.head current=cursor while cursor.next != None: current = cursor cursor=cursor.next ele=cursor.ele current.next=None return ele # def remove(self,item): #方法一,代码复用 # if self.length()==0: # raise error("此列表中没有元素!") # else: # index=self.getIndex(item) # if index>0: # self.delete(index) # else: # raise error("在列表中找不到该项!") def remove(self,item): #删除任意元素 cursor=self.head pre=None while cursor != None: if cursor.ele==item: if not pre: self.head=cursor.next else: pre.next=cursor.next break else: pre=cursor cursor=cursor.next def delete(self,index): #删除输入下标的元素 if index<0 or index>self.length()-1: raise error("输入的下标超出范围!") else: if index==0: self.head=self.head.next else: num=0 cursor=self.head current=cursor while num != index: current=cursor cursor=cursor.next num+=1 current.next=cursor.next def __iter__(self): #将这个链表变成可迭代对象(即可遍历) return self def __next__(self): if self.pos<self.length(): self.pos+=1 num=0 cursor=self.head while cursor != None: num+=1 current=cursor cursor=cursor.next if num==self.pos: return current.ele else: raise StopIteration arr=mylist() arr.empty() # arr.add("a") # arr.append("b") # arr.insert(2,"f") # arr.insert(2,"f") # arr.insert(2,"f") # arr.insert(2,"f") # arr.insert(2,"f") # arr.append("c") # arr.append("d") # arr.append("e") # arr.remove("f") # arr.delete(0) # for item in arr: # print(item) # print(arr.empty()) # print(arr.length()) # print(arr.getIndex("g")) # print(arr.getEle(3))
-
单向循环链表
#用面向对象的方式、单向循环链表的思想创建一个类似列表的数据类型
class error(Exception): #继承Python异常类
def init(self,msg):
super(error,self).init()
self.msg=msg
def str(self):
return self.msg #抛出异常class Node: #创建节点 def __init__(self,item=None): self.ele=item self.next=None class mylist: def __init__(self,node=None): self.head=node #初始化头部 self.next=None #下一个地址为空 self.pos=0 def empty(self): #判断是否为空 return self.head==None def length(self): #计算长度 num = 0 if self.empty(): return num else: num=1 cursor=self.head while cursor.next != self.head: cursor=cursor.next num+=1 return num def add(self,item): #从开始添加数据 if self.empty(): node=Node(item) self.head=node node.next=self.head # self.head.next=self.head else: node=Node(item) node.next=self.head cursor=self.head while cursor.next != self.head: cursor=cursor.next cursor.next=self.head self.head = node cursor.next=self.head def append(self,item): #在最后添加元素 if self.empty(): node=Node(item) self.head=node node.next=self.head else: node = Node(item) node.next = self.head cursor = self.head while cursor.next != self.head: cursor = cursor.next cursor.next=node node.next=self.head def pop(self): #在最后删除元素 if self.empty(): raise error("该列表是空的!") else: cursor = self.head # current=cursor while cursor.next != self.head: current=cursor cursor = cursor.next ele=cursor.ele current.next=self.head return ele def getEle(self,index): #获取输入下标的元素 if index<0 or index>self.length()-1: raise error("输入的下标超出范围!") else: num=0 cursor=self.head while num<index: cursor=cursor.next num+=1 return cursor.ele def getIndex(self,item): #获取输入元素的下标 node=Node(item) num=0 cursor=self.head while num<self.length(): if cursor.ele == node.ele: return num else: cursor=cursor.next num+=1 return -1 # def remove(self,item): #方法一,代码复用 # if self.length()==0: # raise error("此列表中没有元素!") # else: # index=self.getIndex(item) # if index>0: # self.delete(index) # else: # raise error("在列表中找不到该项!") def remove(self,item): #删除输入的元素 cursor = self.head pre = None while cursor != None: if cursor.ele == item: if not pre: self.head = cursor.next else: pre.next = cursor.next break else: pre = cursor cursor = cursor.next def delete(self,index): #删除输入下标的元素 if index<0 or index>self.length()-1: raise error("输入的下标超出范围!") else: if index==0: self.head=self.head.next else: num=0 cursor=self.head while num != index: current=cursor cursor=cursor.next num+=1 current.next=cursor.next def __iter__(self): #将链表变为可迭代对象(即可遍历) return self def __next__(self): if self.pos<self.length(): self.pos+=1 num=0 cursor=self.head while cursor != None: num+=1 current=cursor cursor=cursor.next if num==self.pos: return current.ele else: raise StopIteration arr=mylist() arr.empty() # arr.add("t") # arr.add("a") # arr.append("b") # arr.append("c") # arr.append("d") # arr.pop() # print(arr.length()) # for item in arr: # print(item)
-
双向不循环链表
#用面向对象的方式、双向不循环链表的思想创建一个类似列表的数据类型
class error(Exception): #继承Python异常类
def init(self,msg):
super(error,self).init()
self.msg=msg
def str(self):
return self.msg #抛出异常class Node: #创建节点 def __init__(self,item=None): self.ele=item self.next=None self.pre=None class mylist: def __init__(self,node=None): self.head=node #初始化头部 self.next=None #下一个地址为空 self.pre=None self.pos=0 def empty(self): #判断是否为空 return self.head==None def add(self,item): #从开始添加数据 node=Node(item) if self.empty(): self.head=node else: cursor=self.head node.next=cursor #判断有无数据 如果有放到头部 没有直接添加 cursor.pre=node self.head=node def length(self): #计算长度 cursor=self.head num=0 while cursor != None: cursor.pre=cursor cursor=cursor.next num+=1 return num def append(self,item): #在最后添加数据 node = Node(item) if self.empty(): self.head=node else: cursor=self.head while cursor.next != None: cursor=cursor.next cursor.next=node node.pre=cursor def getEle(self,index): #获取输入下标的元素 if index<0 or index>self.length()-1: raise error("输入的下标超出范围!") else: num=0 cursor=self.head while num<index: cursor=cursor.next num+=1 return cursor.ele def getIndex(self,item): #获取输入元素的下标 node=Node(item) num=0 cursor=self.head while num<self.length(): if cursor.ele == node.ele: return num else: cursor=cursor.next num+=1 return -1 def insert(self,index,item): #在输入下标的位置插入元素 node = Node(item) if index<0 or index>self.length(): raise error("输入的下标超出范围!") else: if index==1: self.add(item) elif index==self.length(): self.append(item) else: num=0 cursor=self.head while num<index-1: cursor=cursor.next num+=1 node.next = cursor.next cursor.next = node node.pre=cursor def pop(self): #在最后删除元素 if self.empty(): return None else: if self.length()==1: ele=self.head.ele self.head=None return ele else: cursor=self.head current=cursor while cursor.next != None: current = cursor cursor=cursor.next ele=cursor.ele current.next=None return ele # def remove(self,item): #方法一,代码复用 # if self.length()==0: # raise error("此列表中没有元素!") # else: # index=self.getIndex(item) # if index>0: # self.delete(index) # else: # raise error("在列表中找不到该项!") def remove(self,item): #删除输入的元素 cursor=self.head pre=None while cursor != None: if cursor.ele==item: if not pre: self.head=cursor.next else: pre.next=cursor.next cursor.pre=pre break else: pre=cursor cursor=cursor.next def delete(self,index): #删除出入下标的元素 if index<0 or index>self.length()-1: raise error("输入的下标超出范围!") else: if index==0: self.head = self.head.next else: num=0 cursor=self.head while num != index: current=cursor cursor=cursor.next num+=1 current.next=cursor.next cursor.pre=current def __iter__(self): #将这个链表变成可迭代对象(即可遍历) return self def __next__(self): if self.pos<self.length(): self.pos+=1 num=0 cursor=self.head while cursor != None: num+=1 current=cursor cursor=cursor.next if num==self.pos: return current.ele else: raise StopIteration arr=mylist() arr.empty() # arr.add("a") # arr.add("b") # arr.add("c") # arr.pop() # arr.append("b") # arr.insert(2,"f") # arr.insert(2,"f") # arr.insert(2,"f") # arr.insert(2,"f") # arr.insert(2,"f") # arr.append("c") # arr.append("d") # arr.append("e") # arr.remove("e") # arr.remove("d") # arr.remove("c") # arr.remove("a") # arr.remove("b") # arr.remove("c") # arr.remove("b") # arr.delete(0) # arr.delete(0) # arr.delete(0) # for item in arr: # print(item) # print(arr.empty()) # print(arr.length()) # print(arr.getIndex("g")) # print(arr.getEle(3))
栈和队列:
栈是一种特殊的线性表(一种受限制的链表)
-
栈:先进后出、后进先出
#使用面向对象的方式实现栈
class stack:
def init(self):
self.box=[]def empty(self): return self.box==[] def length(self): return len(self.box) def push(self,item): return self.box.append(item) def pop(self): return self.box.pop() #利用栈的思想检查在一堆字符串中的括号是否匹配 def mach(msg): # 把一个list当做栈使用 arr = stack() con = "()[]{}" for item in msg: s=item # 如果不是括号则继续 if con.find(s) == -1: continue # 左括号入栈 if s == '(' or s == '[' or s == '{': arr.push(s) continue if arr.length() == 0: return False # 出栈比较是否匹配 p = arr.pop() if (p == '(' and s == ')') or (p == '[' and s == ']') or (p == '{' and s == '}'): continue else: return False if arr.length() > 0: return False return True msg = "{abc}{de}(f)[(g)" result = mach(msg) print(msg, result) msg="sbsbbcd{bkhdbc}[jcdkbkcd(ncjdn]cndj)" result = mach(msg) print(msg,result) #使用栈的思想查找走出迷宫的路 maze=[ [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] ] dirs=[(0,-1),(1,0),(0,1),(-1,0)] #上右下左 def ispass(maze,pos):#判断是否通过 return maze[pos[0]][pos[1]]==0 def mark(maze,pos):#标记函数,迷宫和位置为参数 maze[pos[0]][pos[1]]=2 path=[] #path中包含的就是最后的路径 def find_path(maze,pos,end): #pos代表的是当前位置 mark(maze,pos) if pos==end: path.append(pos) return True for i in range(4): next=pos[0]+dirs[i][0],pos[1]+dirs[i][1] if ispass(maze,next): if find_path(maze, next, end): path.append(pos) return True return False find_path(maze,(1,1),(10,10)) print(path) for item in path: maze[item[0]][item[1]]=3 for y in maze: #1是墙,2是走过的路,3是能走通的路,0是其他的但是没有走过的路 for x in y: if x==1: print("\033[1;;47m " +str(x)+"\033[0m",end="") elif x==2: print("\033[1;;41m " +str(x)+"\033[0m",end="") elif x==3: print("\033[1;;42m * \033[0m",end="") else: print("\033[1;;40m " +str(x)+"\033[0m", end="") print()
-
队列:先进先出、后进后出
#队列的实现
# class queue:
# def init(self):
# self.box=[]
# def empty(self):
# return self.box==[]
# def queue(self,item):
# self.box.append(item)
# def dequeue(self):
# return self.box.pop()#在python中有内置包帮你实现队列 from collections import deque queue=deque() queue.append("a") queue.append("b") queue.append("c") queue.append("d") print(queue.popleft()) print(queue.popleft()) print(queue.popleft()) print(queue.popleft())
在控制台输出颜色:
"\033[1;;41m " * " \033[0m", end=""
\033 表示八进制的ESC键
[ 表示了转义
1 表示要设置的方式(1表示高亮)
; ; 俩分号中间是显示的字体颜色 前景色(30~~37)
41 表示背景色 (40~~47)
m 表示颜色结束
* 表示要显示的内容
"\033[m" 结尾
各种排序算法:
-
冒泡排序
它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果他们的顺序(如从大到小、首字母从A到Z)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素已经排序完成。
#冒泡排序
def bubble_sort(lists):
count=len(lists)
for i in range(0,count):
for j in range(i+1,count):
if lists[i]>lists[j]:
lists[i],lists[j]=lists[j],lists[i]
print(lists)
return lists -
选择排序
选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到全部待排序的数据元素排完。 选择排序是不稳定的排序方法。
#选择排序
def getmin(lists):
min = lists[0];
min_index = 0;
for i in range(0,len(lists)):
if lists[i]<min:
min = lists[i]
min_index = i
return min_indexdef xuanze(arr): newArr = []; for i in range(0,len(arr)): min = getmin(arr); newArr.append(arr.pop(min)) print(newArr) return newArr; def xuanze1(arr): for j in range(len(arr)): index=j for i in range(j+1,len(arr)): if arr[index]>arr[i]: arr[index]=arr[i] arr[j],arr[index]=arr[index],arr[j] return arr
-
快速排序
快速排序(Quicksort)是对冒泡排序的一种改进。 快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
#快速排序
def quick_sort(arr):
if len(arr)<2:
return arr
else:
val=arr[0]
less_than=[m for m in arr if m<val]
base=[m for m in arr if m==val]
more_than=[m for m in arr if m>val]
return kuaisu(less_than)+base+kuaisu(more_than)def quickSort(arr,start,end): if start>=end: # print(arr) return arr left=start right=end temp=arr[left] while left<right: while left<right and temp<arr[right]: right-=1 # arr[left]=arr[right] while left<right and temp>arr[left]: left+=1 # arr[right]=arr[left] arr[left],arr[right]=arr[right],arr[left] arr[left],temp=temp,arr[left] quickSort(arr,start,left-1) quickSort(arr,left+1,end) return arr
-
插入排序
有一个已经有序的数据序列,要求在这个已经排好的数据序列中插入一个数,但要求插入后此数据序列仍然有序,这个时候就要用到一种新的排序方法——插入排序法,插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序,时间复杂度为O(n^2)。是稳定的排序方法。插入算法把要排序的数组分成两部分:第一部分包含了这个数组的所有元素,但将最后一个元素除外(让数组多一个空间才有插入的位置),而第二部分就只包含这一个元素(即待插入元素)。在第一部分排序完成后,再将这个最后元素插入到已排好序的第一部分中。 插入排序的基本思想是:每步将一个待排序的记录,按其关键码值的大小插入前面已经排序的文件中适当位置上,直到全部插入完为止。
#插入排序(打扑克)
def insert_sort(arr):
for i in range(1,len(arr)): # 1 2 3 4 5 6
x = arr[i]
for j in range(i,-1,-1): # 1
# j为当前位置,试探j-1位置
if x < arr[j-1]:
arr[j] = arr[j-1]
# print(arr[j])
else:
# 位置确定为j
break
arr[j] = x
return arrdef insert_sort1(arr): for i in range(1,len(arr)): pre=i-1 current=arr[i] while pre>=0 and current<arr[pre]: arr[pre+1]=arr[pre] pre-=1 arr[pre+1]=current return arr
-
希尔排序
希尔排序(Shell’s Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因D.L.Shell于1959年提出而得名。 希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
#希尔排序
def sher(arr):
leng=len(arr)
val=leng//2
while val>0:
for i in range(val,leng):
pre = i - 1
current = arr[i]
while pre>=0 and current<arr[pre]:
arr[pre + 1] = arr[pre]
pre -= 1
arr[pre + 1] = current
val=val//2
return arr -
归并排序
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
def MergeSort(lists):
if len(lists) <= 1:
return lists
num = int( len(lists) / 2 )
left = MergeSort(lists[:num])
right = MergeSort(lists[num:])
return Merge(left, right)
def Merge(left,right):
r, l=0, 0
result=[]
while l<len(left) and r<len(right):
if left[l] < right[r]:
result.append(left[l])
l += 1
else:
result.append(right[r])
r += 1
result += list(left[l:])
result += list(right[r:])
return result
print MergeSort([1, 2, 3, 4, 5, 6, 7, 90, 21, 23, 45]) -
堆排序
堆排序(英语:Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
#以顺序表的方式操作二叉树
arr=[1,5,6,8,9,2,35,68,45,25]
def duipaixu(arr): #大顶堆
def big(arr,start,length):
next=start2+1
while next<length:
if next+1<length and arr[next]<arr[next+1]:
next+=1
if arr[start]<arr[next]:
arr[start],arr[next]=arr[next],arr[start]
start=next
else:
break
next=next2+1for i in range(len(arr)//2-1,-1,-1): big(arr,i,len(arr)) for i in range(len(arr)-1,-1,-1): #只对前 n 个进行排序时,将第二个参数修改为列表长度 -n temp=arr[i] arr[i]=arr[0] arr[0]=temp big(arr,0,i) return arr print(duipaixu(arr)) '''方式二''' def HeapSort(input_list): # 调整parent结点为大根堆 def HeapAdjust(input_list, parent, length): temp = input_list[parent] child = 2 * parent + 1 while child < length: if child + 1 < length and input_list[child] < input_list[child + 1]: child += 1 if temp > input_list[child]: break input_list[parent] = input_list[child] parent = child child = 2 * child + 1 input_list[parent] = temp if input_list == []: return [] sorted_list = input_list length = len(sorted_list) # 最后一个结点的下标为length//2 # 建立初始大根堆 for i in range(0, length // 2 + 1)[::-1]: HeapAdjust(sorted_list, i, length) for j in range(1, length)[::-1]: # 把堆顶元素即第一大的元素与最后一个元素互换位置 temp = sorted_list[j] sorted_list[j] = sorted_list[0] sorted_list[0] = temp # 换完位置之后将剩余的元素重新调整成大根堆 HeapAdjust(sorted_list, 0, j) print('%dth' % (length - j)) print(sorted_list) return sorted_list
-
计数排序
计数排序是一个非基于比较的排序算法,该算法于1954年由 Harold H. Seward 提出。它的优势在于在对一定范围内的整数排序时,它的复杂度为Ο(n+k)(其中k是整数的范围),快于任何比较排序算法。 [1-2] 当然这是一种牺牲空间换取时间的做法,而且当O(k)>O(nlog(n))的时候其效率反而不如基于比较的排序(基于比较的排序的时间复杂度在理论上的下限是O(nlog(n)), 如归并排序,堆排序)
def sort(a):
n=len(a)
b=[None]*n
for i in range(n):
p=0
q=0
for j in range(n):
if a[j]<a[i]:
p+=1
elif a[j]==a[i]:
q+=1
for k in range(p,p+q):
b[k]=a[i]
print b -
桶排序
桶排序 (Bucket sort)或所谓的箱排序,是一个排序算法,工作的原理是将数组分到有限数量的桶子里。每个桶子再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)。桶排序是鸽巢排序的一种归纳结果。当要被排序的数组内的数值是均匀分配的时候,桶排序使用线性时间(Θ(n))。但桶排序并不是 比较排序,他不受到 O(n log n) 下限的影响。
#桶排序
def tong(arr):
big=max(arr)
bucket=[0]*(big+1)
# bucket=[0 for i in range(big+1)]
for i in arr:
bucket[i]+=1
arr1=[]
for index in range(len(bucket)):
if bucket[index] != 0:
for j in range(bucket[index]):
arr1.append(index)
return arr1 -
基数排序
基数排序(radix sort)属于“分配式排序”(distribution sort),又称“桶子法”(bucket sort)或bin sort,顾名思义,它是透过键值的部份资讯,将要排序的元素分配至某些“桶”中,藉以达到排序的作用,基数排序法是属于稳定性的排序,其时间复杂度为O (nlog®m),其中r为所采取的基数,而m为堆数,在某些时候,基数排序法的效率高于其它的稳定性排序法。
import mathdef sort(a, radix=10): """a为整数列表, radix为基数""" K = int(math.ceil(math.log(max(a), radix))) # 用K位数可表示任意整数 bucket = [[] for i in range(radix)] # 不能用 [[]]*radix for i in range(1, K+1): # K次循环 for val in a: bucket[val%(radix**i)/(radix**(i-1))].append(val) # 析取整数第K位数字 (从低到高) del a[:] for each in bucket: a.extend(each) # 桶合并 bucket = [[] for i in range(radix)]
树结构:
常用术语:
- 节点的度:一个节点含有的子数的个数成为该节点的度
- 树 的度:一棵树中,最大的节点的度叫做树的度
- 叶节点或终端节点:度为零的节点
种类:
- 无序树:若将树中每个结点的各子树看成是从左到右是没有次序的(即能互换),则称该树为无序树(UnorderedTree )
- 有序树:若将树中每个结点的各子树看成是从左到右有次序的(即不能互换),则称该树为有序树(Ordered Tree)
- 二叉树:每一个节点的子节点至多有两个
- 完全二叉树
- 满二叉树
- 平衡二叉树
- 排序二叉树
- 霍夫曼树(哈夫曼树):最优二叉树
- B树(文档、文件夹搜索)
- 二叉树:每一个节点的子节点至多有两个
二叉树的性质(特性)
- 性质1:在二叉树的第 i 层上至多有2*(i-1)个节点
- 性质2:在深度为k的二叉树至多有2*k-1个节点
- 性质3:对于任意一个二叉树,如果叶节点数为N0,而度数为2的节点数为N2,则N0=N2+1
- 性质4:具有n个节点的完全二叉树的深度必为(log2n)+1,取整数
- 性质5:对于完全二叉树,若从上到下,从左到右编号,则编号为 i 的节点,其做孩子编号必为 2i ,其右孩子的编号必为2i+1,其双亲的编号必为i/2(i=1是为根节点,除外)(从0开始计数,左为2i+1 右为2i+2)
- 性质6:在完全二叉树中,最后一个非叶节点的下标为n/2-1
堆排序
- 大顶堆(由小到大排序):上面节点的值永远比下面节点的值大
- 小顶堆(由大到小排序):上面节点的值永远比下面节点的值小
二叉树算法展示:
'''
将一个百分制的成绩转化为1,2,3,4,5
'''
def fenshu():
score=int(input("请输入分数:"))
# score=60
if score<60:
print(1)
elif score>=60 and score<70:
print(2)
elif score>=70 and score<80:
print(3)
elif score>=80 and score<90:
print(4)
else:
print(5)
def fenshu1(): #二叉树改进算法
score=int(input("请输入分数:"))
# score=60
if score<80:
if score<70:
if score<60:
print(1)
else:
print(2)
else:
print(3)
else:
if score<90:
print(4)
else:
print(5)
以栈的方式实现二叉树:
class myTree:
def __init__(self,node=None):
self.root=node
def empty(self):
return self.root==None
def add(self,item):
node=Node(item)
if self.empty():
self.root=node
else:
queue=[self.root]
while queue:
current=queue.pop(0)
if current.left==None:
current.left=node
queue.append(current.left)
return
elif current.right==None:
current.right=node
queue.append(current.right)
return
else:
queue.append(current.left)
queue.append(current.right)
def loop(self): #广度优先(层次遍历)
if self.empty():
return
queue=[self.root]
while queue:
current=queue.pop(0)
print(current.ele)
if current.left != None:
queue.append(current.left)
if current.right != None:
queue.append(current.right)
def deep_top(self,node): #先序遍历
if node==None:
return
print(node.ele,end=" ")
self.deep_top(node.left)
self.deep_top(node.right)
def deep_left(self,node): #中序遍历
if node==None:
return
self.deep_top(node.left)
print(node.ele,end=" ")
self.deep_top(node.right)
def deep_last(self,node): #后序遍历
if node==None:
return
self.deep_top(node.left)
self.deep_top(node.right)
print(node.ele,end=" ")
tree=myTree()
tree.add("a")
tree.add("b")
tree.add("c")
tree.add("d")
tree.add("e")
tree.add("f")
tree.add("g")
tree.loop()
tree.deep_top(tree.root)
print()
tree.deep_left(tree.root)
print()
tree.deep_last(tree.root)
print()
广度优先二叉树(层次)
深度优先二叉树(深度)
- 前序:根 左 右
- 中序:左 根 右
- 后序:左 右 根
查找:
-
二分法(折半):前提是排好序的数据
def find(arr,val): #以递归的思想实现二分查找
if arr==[]:
return False
mid=len(arr)//2
if arr[mid]==val:
return True
if val<arr[mid]:
return find(arr[:mid],val)
else:
return find(arr[mid+1:],val)arr=[1,4,8,8,4,6,646,45,4,6] print(find(arr,99)) arr=[0,1,3,9,12,35,49,58,81] def find1(arr,item): #以左右游标的思想进行二分查找 if arr==[]: return False left=0 right=len(arr)-1 while left<right: middle=(left+right)//2 if arr[middle]==item: return True elif item<arr[middle]: right=middle-1 else: left=middle+1 return False print(find1(arr,49))