算法(Algorithm): 一个计算过程, 解决问题的方法

1、递归的两个特点
- 调用自身
- 结束条件 时间复杂度
- 时间复杂度是用来估计算法运行时间的一个式子(单位)
- 一般来说,时间复杂度高的算法比复杂度低的算法快
空间复杂度
用来评估算法内存占用大小的一个式子 列表查找: 从列表中查找指定元素
输入:无序
输出:有序
顺序查找:
从列表第一个元素开始,顺序进行搜索,直到找到为止。 二分查找:
从有序列表的候选区data[0:n]开始,通过对待查找的值与候选区中间值的比较,可以使候选区减少一半。
找任何一个数,次数都不会超过LOG 2 N, 2为底N的对数, 2 ** x <= n
在10**5内找一个数,那么找到它,需要找的次数 2 **x < 10**5, x = 16 列表排序: 列表排序: 将无序列表变为有序列表
应用场景:
各种榜单、表格、给二分排序用,给其它算法用 排序lowB三人组:
冒泡排序
选择排序
插入排序
快速排序
排序NB二人组:
- 堆排序
- 归并排序
没什么人用的排序:
基数排序
希尔排序
桶排序 一、LOW
时间复杂度:O(n**2)
空间复杂度:O(1) 冒泡排序:
时间复杂度:O(n**2)
random.shuffle(data) #
排序一万个数得10多秒,
首先,列表每两个相邻的数,如果前边的比后边的大,那么交换这两个数
如果冒泡排序中执行一趟而没有交换,则列表已经是有序状态,可以直接结束算法。
选择排序
一趟遍历记录最小的数,放到第一个位置;
再一趟遍历记录剩余列表中最小的数,继续放置;
找到最小的数:
if xx < xxx: xxx=xx, xx,xx=xx,xx, 小于则交换
插入排序:(打牌一样,来一个数、插入一次)
列表被分为有序区和无序区两个部份。最初有序区只有一个元素。
每次从无序区选择一个元素,插入到有序区的位置,直到无序区变空。 二、快排(快速排序)
快速排序:
好写的排序算法里最快的
快的排序里最好写的 快排思路:
取一个元素P(第一个元素), 使P归位;
列表被P分成两部分,左边都比P小,右边都比P大;
递归完成排序 效率:
快排相比冒泡快了多少?
问题:
最坏情况
递归 最好情况 一般情况 最坏情况
快排 O(nlogn) O(nlogn) O(n^2)
冒泡 O(n) O(n^2) O(n^2) 代码实现: 堆
树是一种数据结构 比如:目录结构
树是一种可以递归定义的数据结构
树是由n个节点组成的集合:
如果n=0,那这是一棵空树;
如果n>0,那存在1个节点作为树的根节点,其他节点可以分为m个集合,每个集合本身又是一棵树。
一些概念
根节点、叶子节点
树的深度(高度)
树的度: 有几个子结点(下一层,)
孩子节点/父节点
子树 二叉树:度不超过2的树(节点最多有两个叉)
满二叉树
完全二叉树 二叉树的存储方式:
链式存储方式
顺序存储方式(列表) 父节点和左孩子节点的编号下标有什么关系?
i -> 2*i + 1 父节点和右孩子节点的编号下标有什么关系?
i -> 2i+2
比如,我们要找根节点左孩子的左孩子
x = 2*(2*0+1)+1 = 3, list_[3]
最后一个有子结点的堆
x = n // 2 - 1 # n = len() 二叉树是度不超过2的树
满二叉树与完全二叉树
(完全)二叉树可以用列表来存储,通过规律可以从父亲找到孩子或从孩子找到父亲 堆
大根堆:一棵完全二叉树,满足任一节点都比其孩子节点大
小根堆:一棵完全二叉树,满足任一节点都比其孩子节点小 假设:节点的左右子树都是堆,但自身不是堆
当根节点的左右子树都是堆时,可以通过一次向下的调整来将其变换成一个堆
堆排序过程:
建立堆
得到堆顶元素,为最大元素
去掉堆顶,将堆最后一个元素放到堆顶,此时可通过一次调整重新使堆有序。
堆顶元素为第二大元素。
重复步骤3,直到堆变空。 归并:
- 假设现在的列表分成两段有序, 如何将其合成为一个有序列表
- 从两边分别取,取最小的 ===> 这个过程就叫归并
肯定有一边先取完,剩下的就不必再比较,直接取下来,xx[:] = xxx[:] 有了归并如何使用?
分解: 将列表越分越小,直至分成一个元素。
一个元素是有序的
合并: 将两个有序列表归并,列表越来越大。 时间复杂度:O(nlogn)
空间复杂度:O(n) * 三种排序算法的时间复杂度是O(nlogn)
- 一般情况下,就运行时间而言:
快速排序 < 归并排序 < 堆排序 - 三种排序算法的缺点:
- 快速排序: 极端情况下排序效率底
- 归并排序: 需要额外的内存开销
- 堆排序: 在快的排序算法中相对较慢 希尔排序:
希尔排序是一种分组插入排序算法。
首先取一个整数d1=n/2,将元素分为d1个组,每组相邻量元素之间距离为d1,在各组内进行直接插入排序;
取第二个整数d2=d1/2,重复上述分组排序过程,直到di=1,即所有元素在同一组内进行直接插入排序。
希尔排序每趟并不使某些元素有序,而是使整体数据越来越接近有序;最后一趟排序使得所有数据有序。 时间复杂度: O((1+T)n) # O(1.3n) 排序:
- 两个排序条件
姓名、年龄
排序的稳定性, 冒泡、快排、堆、归并
算法稳定性:
就是算法的稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录(有相同的元素),
若经过排序,这些记录的相对次序保持不变,
即在原序列中,ri=rj,且ri在rj之前,而在排序后的序列中,ri仍在rj之前,则称这种排序算法是稳定的;否则称为不稳定的。 练习1:
1、现在有一个列表,列表中的数范围都在0到100之间,列表长度大约为100万,设计算法在O(n)时间复杂度内将列表进行排序。
- 计数排序,统计每个数出现的次数。只能是数值型,然后再写回列表
这时使用快排等会比较慢,有大量重复数据 2、有N(n>1000000)个数,如何取出最大的前10个数?
- 取列表前10个元素建立一个小根堆。堆顶就是目前第10大的数
- 依次向后遍历原列表,对于列表中的元素,如果小于堆顶,则忽略该元素;如果大于堆顶,则将堆顶更换为该元素,并且对堆进行一次调整;
- 遍历列表所有元素后,倒序弹出堆顶。 堆----> 优先排列
练习2:
给定一个升序列表和一个整数,返回该整数在列表中的下标范围。
例如: 列表[1,2,3,3,3,4,4,5], 若查找3,则返回(2,4);若查找0,由返回(0,0) study
#-*- coding: utf-8 -*-
# Wind clear raise
# 2017/7/22 下午4:33 import random
import runtime @runtime.call_time
def bubble_sort(x):
print(id(x))
for i in range(len(x)-1): for j in range(len(x) -i - 1):
# 相邻两个数相比较
#
if x[j] > x[j+1]:
x[j], x[j+1] = x[j+1], x[j] @runtime.call_time
def bubble_sort_2(x):
"""冒泡排序优化"""
print(id(x))
for i in range(len(x)-1):
exchange = False
for j in range(len(x) -i - 1):
# 相邻两个数相比较
#
if x[j] > x[j+1]:
x[j], x[j+1] = x[j+1], x[j]
exchange = True
if not exchange:
print(exchange)
break #选择排序
@runtime.call_time
def select_sort(li):
for i in range(len(li) -1 ):
min_loc = i
for j in range(i+1, len(li)):
if li[j] < li[min_loc]:
min_loc = j
li[i], li[min_loc] = li[min_loc], li[i] #插入排序
@runtime.call_time
def insert_sort(li):
for i in range(1, len(li)):
tmp = li[i]
j = i - 1
while j >=0 and tmp < li[j]:
li[j+1] = li[j]
j -= 1
li[j+1] = tmp ## 快排 def quick_sort(data, left, right):
if left < right:
mid = partition(data, left, right)
quick_sort(data, left, mid-1)
quick_sort(data, mid + 1, right) def partition(data, left, right): tmp = data[left]
while left < right: # left == right 终止
while left < right and data[right] >= tmp:
right -= 1
data[left] = data[right] while left < right and data[left] <= tmp:
left += 1
data[right] = data[left] data[left] = tmp return left @runtime.call_time
def quick_sort_x(data): quick_sort(data, 0 , len(data) -1) #堆
def sift(data, low, high):
i = low
j = 2 * i + 1
tmp = data[i] while j <= high: # 孩子在堆里
if j < high and data[j] < data[j+1]: # 如果有右孩子且比左孩子大
j += 1
if tmp < data[j]: # 孩子比根大
data[i] = data[j]
i = j # 新的根
j = 2 * i + 1 # 新的孩子 else:
break
data[i] = tmp
# 降序
def sift_desc(data, low, high):
i = low
j = 2 * i + 1
tmp = data[i] while j <= high: # 孩子在堆里
if j < high and data[j] > data[j+1]: # 如果有右孩子且比左孩子小
j += 1
if tmp > data[j]: # 孩子比根小
data[i] = data[j]
i = j # 新的根
j = 2 * i + 1 # 新的孩子 else:
break
data[i] = tmp @runtime.call_time
def heap_sort(data): n = len(data)
# print(data)
# 最后一个有子结点的堆 n // 2 -1
for i in range(n // 2 -1, -1, -1):
sift(data, i, n -1)
# 堆建好了。。
# print(data) for i in range(n -1, -1, -1): # i指向堆的最后
data[0], data[i] = data[i], data[0] # 领导退休,下属上位
sift(data, 0, i - 1) # 调整新领导
# print(data) ## 归并
def merge(li, low, mid, high):
i = low
j = mid + 1
ltmp = []
while i <= mid and j<=high:
if li[i] < li[j]:
ltmp.append(li[i])
i += 1
else:
ltmp.append(li[j])
j += 1 while i<= mid:
ltmp.append(li[i])
i += 1
while j<= high:
ltmp.append(li[j])
j += 1 li[low:high+1] = ltmp
def mergesort(li, low, high):
if low < high:
mid = (low + high) // 2
# print(low, high, mid)
mergesort(li, low, mid)
mergesort(li, mid+1, high)
merge(li, low, mid, high) @runtime.call_time
def mergesort_x(*args):
mergesort(*args) # 希尔
@runtime.call_time
def shell_sort(li):
gap = len(li) // 2
while gap >0:
for i in range(gap, len(li)):
tmp = li[i]
j = i - gap
while j >= 0 and tmp < li[j]:
li[j+gap] = li[j]
j -= gap
li[j + gap] = tmp
gap //= 2 import copy data = list(range(10000))
#
random.shuffle(data) # 打乱一个列表
data1 = copy.deepcopy(data)
data2 = copy.deepcopy(data)
data3 = copy.deepcopy(data)
data4 = copy.deepcopy(data)
# data = [1, 5, 3, 7, 8, 9] # bubble_sort(data)
# random.shuffle(data)
# bubble_sort_2(data)
# print(id(data)) ##xxx 1 5 3 7 8 9
## 5 4 8 3 9
# data = [5, 4, 8, 3, 9] # insert_sort(data2)
# select_sort(data1)
# bubble_sort_2(data4)
# print(data)
print("快排")
quick_sort_x(data3)
# print(data3)
print("堆")
heap_sort(data1) # 归并
print("归并")
mergesort_x(data4, 0, len(data4)-1) print("shell sort")
shell_sort(data2)
# print(data2) def topn(li, n=10):
heap = li[0:n]
for i in range(n//2-1, -1, -1):
sift(heap, i, n-1) for i in range(n, len(li)):
if li[i] > heap[0]:
heap[0] = li[i]
sift(heap, 0, n -1 ) for i in range(n -1, -1, -1):
heap[0], heap[i] = heap[i], heap[0]
sift(heap, 0, i-1) return heap

study.py


Python 第八阶段 学习记录之---算法的更多相关文章

  1. Python 第五阶段 学习记录之---Django 进阶

    Model 一.创建表 1.基本结构 字段 AutoField(Field) - int自增列,必须填入参数 primary_key=True BigAutoField(AutoField) - bi ...

  2. Python 第五阶段 学习记录之---Django 基础

    Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM.模型绑定.模板引擎.缓存.Session等诸多功能. ...

  3. Python 第五阶段 学习记录之--- Web框架

    什么是web服务器的原理是什么 Web框架本质 众所周知,对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. #!/usr/bin/env pyt ...

  4. Python 第五阶段 学习记录之----ORM

    ORM: orm英文全称object relational mapping,就是对象映射关系程序,简单来说我们类似python这种面向对象的程序来说一切皆对象,但是我们使用的数据库却都是关系型的,为了 ...

  5. Python 第五阶段 学习记录之----rabbmit

    消息服务器rabbmit RabbitMQ 消息队列 python里有两个Q, threading queue.不同线程间数据交互 进程Queue: 不同进程间交互这个说法是错误的. 这个是用于父进程 ...

  6. python 第四阶段 学习记录之----异步

    异步: 知识情况: 1.多线程, 多线程使用场景 1.IO操作不占CPU,读写数据(网络中.系统中) 2.计算占CPU, 3.上下文切换不占CPU.它消耗资源 python多线程 不适合CPU密集型的 ...

  7. Python 第四阶段 学习记录之----多线程

    多线程 多线程例子, 注释部份即为多线程的使用 #-*- coding: utf-8 -*- # Wind clear raise # 2017/3/5 下午2:34 import socket im ...

  8. 孤荷凌寒自学python第八十二天学习爬取图片2

    孤荷凌寒自学python第八十二天学习爬取图片2 (完整学习过程屏幕记录视频地址在文末) 今天在昨天基本尝试成功的基础上,继续完善了文字和图片的同时爬取并存放在word文档中. 一.我准备爬取一个有文 ...

  9. Python第八课学习

    Python第八课学习 www.cnblogs.com/resn/p/5800922.html 1 Ubuntu学习 根 / /: 所有目录都在 /boot : boot配置文件,内核和其他 linu ...

随机推荐

  1. ubuntu下vim使用方法

    按下's'可对文本进行编辑 按下'ESC'再输入':',之后输入wq是保存再退出,输入q是直接退出.如果是只读read only模式则需要输入'wq!'保存退出.

  2. Hibernate 配置文件的基础配置

    Hibernate 配置文件主要用于配置数据库连接和 Hibernate运行时所需的各种属性 每个 Hibernate 配置文件对应一个 Configuration 对象 Hibernate.cfg. ...

  3. Module(CP343-1)Advanced system error SDB generation Error in rule file or rule file not found

    报这个故障的原因是因为安装目录下缺少三个 err文件.只要从好的目录下拷贝过来即可. C:\Program Files (x86)\SIEMENS\Step7\s7wbx\rul

  4. Java 基础:认识&理解关键字 native 实战篇

    Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket 泥瓦匠初次遇见 navicat 是在 java.lang.Object 源码中的一个hashCode方 ...

  5. c#中string的一些基本用法

    .string的Split方法的使用 这个例子就是通过制定的符号来将词组分开,Splite(分割的字符,分割的份数) using System; using System.Collections; p ...

  6. Jquery常用的方法总结

    1.关于页面元素的引用通过jquery的$()引用元素包括通过id.class.元素名以及元素的层级关系及dom或者xpath条件等方法,且返回的对象为jquery对象(集合对象),不能直接调用dom ...

  7. Vue 前端面试题

    Vue 前端面试题 1. 说一下 Vue 的双向绑定数据的原理 vue 实现数据双向绑定主要是:采用数据劫持结合“发布者 - 订阅者”模式的方式,通过 Object.defineProperty() ...

  8. Linux和Shell教程

    文档资料参考: 参考:http://www.runoob.com/linux/linux-tutorial.html 软件下载参考: centos 下载地址:https://www.centos.or ...

  9. 线性表->链式存储->循环链表

    文字描述 循环链表是另一种形式的链式存储结构.它的特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环.由此,从表中任一结点出发均可找到表中其他结点. 示意图 算法分析 插入.删除.查找等同单 ...

  10. Jmeter压测基础(二)——Badboy功能、Jmeter参数化、检查点、集合点、动态关联、图形监控

    Badboy 以下稍微介绍一下badboy的部分功能: 1.Record;play(badboy打开后默认是recording状态) 2.Assertion(检查点/断言) 3.Variable: t ...