Python全栈开发之5、几种常见的排序算法以及collections模块提供的数据结构

  在面试中,经常会遇到一些考排序算法的题,在这里,我就简单了列举了几种最常见的排序算法供大家学习,说不定以后哪天面试正好用上,文章后半段则介绍一下collections模块,因为这个模块相对于python提供的基本数据结构(list,tuple,dict)不被人们所熟悉,但是如果你对他们了解的话,用起来也是非常方便高效的。

排序算法

一、冒泡排序(BubbleSort)

步骤:

  • 比较相邻的元素,如果第一个比第二个大,就交换他们两个。
  • 循环一遍后,最大的数就“浮”到了列表最后的位置。
  • 将剩下的数再次循环,直道所有的排序完成

代码如下:

def swap(a,b):            #一种巧妙交换两个数的位置而不用第三个变量的方法
    a=b-a
    b=b-a                 # b=b-(b-a) = a
    a=b+a                 # a=a+(b-a) = b
    return a,b

def BubbleSort(l):                      # 冒泡排序
    for i in range(1,len(l)):
        for j in range(0,len(l)-i):           # 每次循环减i是因为最后面的数已经排好序
            if l[j]>l[j+1]:
                l[j],l[j+1]=l[j+1],l[j]        # 交换两个数,这里用的交换是python里面特有的交换方式
    return l
print(BubbleSort([555,2,3,2,3,1,19,3.5,27,24]))    # [1, 2, 2, 3, 3, 3.5, 19, 24, 27, 555]

二、选择排序 SelectionSort

步骤:

  • 在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
  • 再从剩余未排序元素中继续寻找最小(大)元素,然后放到排序序列的起始。
  • 循环下去,直道所有的数排序完成

代码如下:

def SelectionSort(l):
    for i in range(len(l)):
        min = i                                     #存放最小元素的下标
        for j in range(i+1,len(l)):
            if l[j]<l[min]:
                min=j                              #记下最小元素的下标
        l[i],l[min] = l[min],l[i]                  #将最小元素放到列表起始位置
    return l
print(SelectionSort([555,2,3,2,3,1,19,3.5,27,24]))   #[1, 2, 2, 3, 3, 3.5, 19, 24, 27, 555]

三、插入排序 InsertionSort

步骤:

  • 从第一个元素开始可以认为已经被排序,取出下一个元素,在已经排序的元素序列中从后向前扫描
  • 如果该元素(已排序)大于新元素,将该元素移到下一位置,直到找到已排序的元素小于或者等于新元素的位置
  • 将新元素插入到该位置后,如此反复循环,直道所有的排好序

代码如下:

def InsertionSort(l):
    for i in range(1,len(l)):
        if l[i]<l[i-1]:
            temp=l[i]                               # 应该插入的数赋值给变量temp
            for j in range(i-1,-1,-1):              # 从已排好的序列往前循环
                if l[j]>temp:
                    l[j+1] = l[j]
                    index=j                         # 记下应该插入的位置
                else:
                    break
            l[index]=temp
    return l
print(InsertionSort([555,2,3,2,3,1,19,3.5,27,24]))   # [1, 2, 2, 3, 3, 3.5, 19, 24, 27, 555]

四、快速排序 QuickSort

步骤:

  • 从数列中挑出一个元素作为基准数(这里我选择的是第一个数)
  • 将比基准数大的放到左边,小于或等于它的数都放到右边
  • 再对左右区间递归执行上一步,直至各区间只有一个数

代码如下:

#这里我用了递归和列表推到式(不明白列表推到式的可暂时跳过,后面讲到)
def QuickSort(l):
    if len(l)<=1:
        return l
    return QuickSort([lt for lt in l[1:] if lt<l[0]]) + l[0:1] + QuickSort([ge for ge in l[1:] if ge>=l[0]])

print(QuickSort([555,2,3,2,3,1,19,3.5,27,24]))   # [1, 2, 2, 3, 3, 3.5, 19, 24, 27, 555]

有关排序的算法暂时先写这么多,还有一些排序算法没有写,有的排序算法也可以用几种不同的方法实现,如果后续时间充足的话,再来完善,下面讲一下collctions模块

collections模块  

一、deque

  deque是一个双端队列,还记得以前的列表,一般情况下都是从尾部添加删除,而deque允许从任意一端增加或删除元素,deque的用法和list很像,下面的代码主要来看一下一些特有的用法,

#原生的list也可以从头部添加和取出元素,list对象的这两种用法的时间复杂度是 O(n) ,
#也就是说随着元素数量的增加耗时呈线性上升,而使用deque对象则是O(1)的复杂度
from collections import deque

d=deque(‘adf‘)
print(type(d))                       # <class ‘collections.deque‘>
d.appendleft([1,2,3])                # 从左端插入列别
print(d)                             # deque([[1, 2, 3], ‘a‘, ‘d‘, ‘f‘])
d.extendleft(‘gssg‘)                 # 从左端扩展一个可迭代的对象
print(d)                             # deque([‘g‘, ‘s‘, ‘s‘, ‘g‘, [1, 2, 3], ‘a‘, ‘d‘, ‘f‘])
print(d.popleft())                   # 左端删除元素 g
print(d)                             # deque([‘s‘, ‘s‘, ‘g‘, [1, 2, 3], ‘a‘, ‘d‘, ‘f‘])
d.rotate(1)                          # 1代表循环移动一步,相当于 d.appendleft(d.pop())
print(d)                             # deque([‘f‘, ‘s‘, ‘s‘, ‘g‘, [1, 2, 3], ‘a‘, ‘d‘])
print(d[4])                          #  支持索引,[1, 2, 3]
for i in d:
    print(i)                         # 支持for循环

# 除此之外,index(),append(),extend(),reverse(),remove(),pop(),insert()等方法和列表一样就不在说了

二、namedtuple 

namedtuple()用来创建一个自定义的tuple对象,并且规定了tuple元素的个数,并可以用属性而不是索引来引用tuple的某个元素。

from collections import namedtuple
# 如果我们想用元组表示一个点的话(x,y),
# 这样写并不能很清楚的表达意思,这时候就可以用namedtuple,
# 它具备tuple的不变性,又可以根据属性来引用

Point=namedtuple(‘Point‘,[‘x‘,‘y‘])  # 用 namedtuple函数,创建一个自定义的tuple对象 Point
p1=Point(11,y=2)                     # 创建一个实例 p1
p2=Point(2,3)
print(p1.x)                          # 11  根据属性来获取值
print(p2[1])                         # 3   同样支持索引

p3=Point(*(55,22))                   # 传入元组的话用*转换
print(p3.x)                          # 55
p4=Point(**{‘x‘:1,‘y‘:1})            # 传入字典的话用**转换
print(p4.x)                          # 1

三、defaultdict

  使用dict时,如果引用的Key不存在,就会抛出KeyError,而且py3中没有has_key的方法,每次使用前需要使用in判断。如果希望key不存在时,返回一个默认值,就可以用defaultdict。

#传入一个默认的工厂方法,那么请求一个不存在的key时,
#便会调用这个工厂方法使用其结果来作为这个key的默认值。

dd=defaultdict(lambda :‘NA‘)         # 当key不存在调用lammbda函数
dd[‘x‘]=2
print(dd[‘y‘])                       # 键不存在,返回NA
print(dd[‘x‘])                       # 存在,值为2
print(dd)                            # defaultdict(<function <lambda> at .., {‘x‘: 2, ‘y‘: ‘NA‘})

#defaultdict还有一种神奇的用法,用作统计,看下面的代码
s = [(‘yellow‘, 1), (‘blue‘, 2), (‘yellow‘, 3), (‘blue‘, 4), (‘red‘, 1)]
d = defaultdict(list)
for k, v in s:
    d[k].append(v)  # key不存在的时候返回一个列表,然后用append添加相应的元素
print(d)            # defaultdict(<class ‘list‘>, {‘yellow‘: [1, 3], ‘red‘: [1], ‘blue‘: [2, 4]})

四、OrderedDict

  以前使用dict的时候,由于dict是无序的总是不能做循环迭代等,如果我们想保持Key的顺序可以使用OrderedDict,注意这里Key的顺序是指Key插入的顺序,而不是用Key本身排序。

from collections import OrderedDict
od=OrderedDict()
od[‘x‘]=1
od[‘y‘]=2
od[‘a‘]=3
print(od)             # OrderedDict([(‘x‘, 1), (‘y‘, 2), (‘a‘, 3)])
for i in od:
    print(i)          # 打印顺序 x->y->a,读者可以下去多试几次看结果是否一样
print(od.popitem())   # 将(‘a‘, 3)弹出, LIFO(后进先出)

五、Counter

Counterdict的一个子类,是一个简单的计数器,下面来看一下他的用法

from collections import Counter

c1=Counter(‘ddkhbb‘)           # 传入一个可迭代的对象
print(c1)                      # Counter({‘d‘: 2, ‘b‘: 2, ‘h‘: 1, ‘k‘: 1})
print(c1[‘d‘])                 # 2

# 计数器的更新,增加
c1.update(‘kkk‘)
print(c1)                      # Counter({‘k‘: 4, ‘d‘: 2, ‘b‘: 2, ‘h‘: 1})

# 计数器的更新,减少
c1.subtract(‘kkkkkkkk‘)
print(c1)                      # Counter({‘d‘: 2, ‘b‘: 2, ‘h‘: 1, ‘k‘: -4})

# elements返回一个迭代器,元素被重复了多少次,在该迭代器中就包含多少个该元素。
# 个数小于1的元素不被包含。k数量小于1,就被排除了
print(list(c1.elements()))     # [‘h‘, ‘d‘, ‘d‘, ‘b‘, ‘b‘]

print(c1.most_common(2))       #取出出现次数最多2个元素 [(‘b‘, 2), (‘d‘, 2)]

  

  

  

  

时间: 2024-10-05 11:34:08

Python全栈开发之5、几种常见的排序算法以及collections模块提供的数据结构的相关文章

Python全栈开发之21、django

http://www.cnblogs.com/wupeiqi/articles/5237704.html http://www.cnblogs.com/wupeiqi/articles/5246483.html http://www.cnblogs.com/yuanchenqi/articles/5786089.html 基本配置 一 常用命令 django-admin startproject sitename python manage.py runserver 0.0.0.0 python

Python全栈开发之17、tornado和web基础知识

一.web基础知识 学习web框架之前,先来看一下web基础知识,首先要明白其本质就是socket,用户对应一个socket客户端,但是如果从socket开始开发web应用程序那么效率太了,正确的做法是底层socket处理代码由专门的服务器软件实现,而对于真实开发中的python web程序来说也是一般会分为两部分:服务器程序和应用程序.服务器程序负责对socket服务器进行封装,并在请求到来时,先经过web服务器,对请求的各种数据进行整理封装.之后web服务器将封装好的数据传递给应用程序,应用

Python全栈开发之Django基础

[TOC] No.1 MVC&MTV MVC M全拼为Model,主要封装对数据库层的访问,对数据库中的数据进行增.删.改.查操作 V全拼为View,用于封装结果,生成页面展示的html内容 C全拼为Controller,用于接收请求,处理业务逻辑,与Model和View交互,返回结果 MTV M全拼为Model,与MVC中的M功能相同,负责和数据库交互,进行数据处理 V全拼为View,与MVC中的C功能相同,接收请求,进行业务处理,返回应答 T全拼为Template,与MVC中的V功能相同,负

Python全栈开发之Django进阶

No.1 静态文件处理 项目中CSS.JS.图片都属于静态文件,一般会将静态文件存到一个单独目录中,便于管理,在HTML页面调用时,需要指定静态文件的路径,Django提供了一种解析静态文件的机制,文件可以放在项目目录下,也可以放在应用目录下 在mysite/setting.py设置文件的物理路径 STATIC_URL = '/static/' STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'static'), ] 在static目录下创建css.js.

Python全栈开发之9、面向对象、元类以及单例

前面一系列博文讲解的都是面向过程的编程,如今是时候来一波面向对象的讲解了 一.简介 面向对象编程是一种编程方式,使用 “类” 和 “对象” 来实现,所以,面向对象编程其实就是对 “类” 和 “对象” 的使用.类就是一个模板,模板里可以包含多个方法(函数),方法里实现各种各样的功能,,对象则是根据模板创建的实例,通过实例,对象可以执行类中的方法,每个对象都拥有相同的方法,但各自的数据可能不同. 二.类.对象和方法 在Python中,定义类是通过class关键字,class后面紧接着是类名,类名通常

Python全栈开发之8、装饰器详解

一文让你彻底明白Python装饰器原理,从此面试工作再也不怕了. 一.装饰器 装饰器可以使函数执行前和执行后分别执行其他的附加功能,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator),装饰器的功能非常强大,但是理解起来有些困难,因此我尽量用最简单的例子一步步的说明这个原理. 1.不带参数的装饰器 假设我定义了一个函数f,想要在不改变原来函数定义的情况下,在函数运行前打印出start,函数运行后打印出end,要实现这样一个功能该怎么实现?看下面如何用一个简单的装饰器来实现

Python全栈开发之12、html

从今天开始,本系列的文章会开始讲前端,从htnl,css,js等,关于python基础的知识可以看我前面的博文,至于python web框架的知识会在前端学习完后开始更新. 一.html相关概念 html是 htyper text markup language 即超文本标记语言,超文本就是指页面内可以包含图片.链接,甚至音乐.程序等非文字元素,而标记语言:即标记(标签)构成的语言. 网页相当于HTML文档,由浏览器解析,用来展示的,静态网页即静态的资源,如xxx.html,动态网页是html代

Python全栈开发之10、网络编程

网络编程就是如何在程序中实现两台计算机的通信,而两台计算机间的通信其实就是两个进程间的通信,进程间的通信主要通过socket(套接字)来描述ip地址(主机)和端口(进程)来实现的,因此我们学习网络编程,必须学习socket 一.socket socket模块是针对 服务器端 和 客户端Socket 进行[打开][读写][关闭],一个完整的套接字模型图如下图所示 在python中读写操作调用的函数有些不一样,下面我们来看一下一个完整的socket(TCP)在服务端和客户端的实现 # server.

Python全栈开发之 Mysql (一)

一: 1.什么是数据库? 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库别说我们在写程序的时候创建的database就是一个数据库 2.什么是 MySQL.Oracle.SQLite.Access.MS SQL Server等 ? 他们均是一个软件,但是都有2个主要的功能 1.将数据保存到文件或内存 2.接受待定的命令,然后对文件进行相应的操作如果有了以上软件,无须自己再去创建文件和文件夹,而是直接传递 命令 给上述软件,让其来进行文件操作,他们统称为数据库管理系统(DBM