常用算法

1 算法的定义

  算法(algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制。也就是说,就能够对一定规范的输入,在有限时间内获得所要求的输出。如果一个算法有缺陷,或不适合与某个问题,执行这个算法将不会解决这个问题。不同的算法可能用不同的时间、空间或效率来完成同样的任何。一个算法的优劣可以用空间复杂度与时间复杂度来衡量。

 算法应具备以下特性:

 a 有穷性(Finiteness) 算法的有穷性是指算法必须能在执行有限个步骤之后终止,并且每一个步骤在可接收的时间内完成。

 b 确切性(Definiteness) 算法的每一步骤必须有确切的定义

 c 输入项(Input) 一个算法有0个或多个输入,以刻画运算对象的初始情况,所谓讴歌输入是指算法本身具备初始条件

 d 输出项(Output) 一个算法有一个或多个输出,以反映对输入数据加工后的结果。没有输出的算法是毫无意义的

 e 可行性(Effectiveness) 算法的每一步都必须是可行的,也就是说,每一步都能够通过执行有限次数完成

 f 正确性

 h 可读性

 g 健壮性

2 算法时间复杂度

 在进行算法分析时,语句总的执行次数T(n)是关于问题规模n的函数,进而分析T(n)随n的变化情况并确定T(n)的数量级。算法的时间复杂度,也就是算法的时间量度,T(n)= O(f(n))。它表示随问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称作算法的渐进时间复杂度,简称为时间复杂度。其中f(n)是问题规模n的某个函数。

 用大写O()来提现算法时间复杂度,称为大O记法。一般,随着n的增长,T(n)增长最慢的算法为最优算法。

 推导大O阶方法:

 * 用常数1取代运行时间中的所有加法常数。

 * 在修改后的运行次数函数中,只保留最高阶项。

   * 如果最高阶项存在且不是1,则去除与这个项相乘的常数。

 常用的时间复杂度有:

  a 常数阶O(1),不管这个常数是多少,我们都记作O(1),而不能是O(3)、O(12)等。

  b 线性阶O(n),线性阶的循环结构会复杂很多,关键就是要分析循环结构的运行情况。

       c 对数阶()

  

  

3 常用排序算法

 a 冒泡排序,复杂度:O(n*n)和O(1)稳定, 原理:将待排序的元素看做是竖着排列的“气泡”,较小的元素比较轻,从而往上浮。

    冒泡排序(Bubble Sort),是一种比较简单的排序算法。

 1 data = [6,5,7,4,8,1,2,9,3,0]
 2 n = 0
 3 for i in range(len(data)):
 4     for j in range(len(data) - i -1):#必须要减一,否则超出列表的范围
 5         if data[j] > data[j+1]:
 6             tmp = data[j]
 7             data[j] = data[j+1]
 8             data[j+1] = tmp
 9 print(data)
10 输出
11 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

 b 插入排序(类似于整理扑克牌),复杂度:O(N*N)和O(1)稳定,原理:逐一取出元素,在已经排序的元素序列中从后往前扫描,放到适当的位置。

1 data_set = [ 9,1,22,9,31,-5,45,3,6,2,11 ]
2 for i in range(len(data_set)):
3     #position  = i
4     while i > 0 and data_set[i] < data_set[i-1]:# 右边小于左边相邻的值
5         tmp = data_set[i]
6         data_set[i] = data_set[i-1]
7         data_set[i-1] = tmp
8         i -= 1 # 前提是右边的序列已经排好
9 print (data_set)

 

 c 选择排序,复杂度:O(N*N)和O(1)不稳定,原理:在长度为N的无序数组中,在第一趟遍历N个数据,找出其中最小的数值与第一个元素交换,第二趟遍历剩下的N-1个数据,找出其中最小的数值与第二个元素交换,如此循环至到选择排序完成。

 1 data_set = [9, 2, 22, 31, 45, 3, 6, 1, 11]
 2 smallest_num_index = 0  # 初始列表最小值,默认为第一个
 3 loop_count = 0
 4 for j in range(len(data_set)):
 5     for i in range(j, len(data_set)):
 6         if data_set[i] < data_set[smallest_num_index]: # 当前值 比之前选出来的最小值 还要小,那就把它换成最小值
 7             smallest_num_index = i
 8         loop_count += 1
 9     else:
10         print("smallest num is ", data_set[smallest_num_index])
11         tmp = data_set[smallest_num_index]
12         data_set[smallest_num_index] = data_set[j]
13         data_set[j] = tmp
14     print(data_set)
15     print("loop times", loop_count)

 

d 快速排序(quick_sort) 时间复杂度为O(nlog2n) 不稳定,原理:选择一个基准元素,通常祖安泽第一个或最后一个元素,通过一趟排序将待排序的记录分割成独立的两部分,其中一部分记录的元素值均比基准元素值小,另一部分记录的元素值比基准值大。

然后分别对这两部分,用同样的方法继续进行排序,直到整个序列有序。

 1 def quickSort(num,l,r):
 2     if l>=r:#如果只有一个数字时,结束递归
 3         return
 4     flag=l
 5     for i in range(l+1,r+1):#默认以第一个数字作为基准数,从第二个数开始比较,生成索引时要注意右部的值
 6         if num[flag]>num[i]:
 7             tmp=num[i]
 8             del num[i]
 9             num.insert(flag,tmp)
10             flag+=1
11             print("~~~",num)
12     quickSort(num,l,flag-1)#将基准数前后部分分别递归排序
13     quickSort(num,flag+1,r)#注意:python递归层次最大为998
14 num=[5,4,7,-2,6,3,2,3]
15 quickSort(num,0,7)
16 print(num)

 

posted @ 2017-09-06 16:30  会开车的好厨师  阅读(130)  评论(0)    收藏  举报