常用数据结构

要点概论

1. 数组(python中用列表代替)

2. 栈和队列

3. 集合

4. 字典

5.collections 数据结构简介

1. 数组

  1.1 列表和数组

    python 语言中没有直接提供数组数据类型,通常使用列表作为数组。列表支持数组要求的 4 中核心操作:创建数组,索引访问,索引赋值,迭代遍历。

示例:生成一副扑克牌(大小王除外),并且随机洗牌后输出一副扑克牌。

import random

SUITS = ['Club','Diamind','Heart','Spade']   # 梅花,方块,红桃,黑桃
RANKS = ['2','3','4','5','6','7','8','9','10','J','Q','K','A']

deck = []  # 一副扑克牌
for rank in RANKS:
    for suit in SUITS:
        card = rank + ' of ' + suit
        deck += [card]
# 洗牌
n = len(deck)
for i in range(n):
    r = random.randrange(i,n)
    temp = deck[r]
    deck[r] = deck[i]
    deck[i] = temp
# 输出一副扑克牌
for s in deck:
    print(s)
    
# 程序部分运行结果如下(结果每次随机):
# 10 of Spade
# 4 of Diamind
# 3 of Heart
# 5 of Spade
# 5 of Heart
# Q of Heart
# 6 of Diamind
# .....
deck.py

  1.2 array.array 对象和数组

    array 模块包含一个array 对象,用于实现其他编程语言中的数组数据结构。

    array 对象是包含相同基本数据类型的列表,其操作与 list 对象基本一致,区别是创建 array 对象时,必须指定其元素累心 typecode ,且其元素只能为该类型,否则会导致 TypeError。

    array 对象构造函数为:

array(typecode[,initializer])

    其中, typecode 为 array 对象中数据元素的类型; initializer 为初始化数据系列或可迭代对象,其元素类型必须与 typecode 一致。

array.array 对象和数组示例:

import array

a = array.array('b',(1,2,3,4,5))

print(a[1])    # 2
a[1] = 22
print(a[1:])    # array('b', [22, 3, 4, 5])

a[0] = 'abc'    # TypeError: an integer is required (got type str)
array.array 对象和数组示例

2. 栈和队列

  2.1 栈的实现:使用列表

    向列表最后位置添加元素和移除元素非常高校和方便,故使用 list ,可以快捷高效地实现栈。 append() 和 pop() 分别对应入栈和出栈操作。

    列表可以实现队列,但并不适合。因为从列表的头部移除一个元素,列表中的所有元素读需要移动位置,所以效率不高。

    可以使用 collections 模块中的 deque 对象。

栈的实现示例【创建一个包含整数 1 和 2 的栈,展示入栈和出栈操作,以及打印栈的内容】:

class Stack:
    def __init__(self,size = 16):   #初始化栈
        self.stack = []
    def push(self,obj):
        self.stack.append(obj)
    def pop(self):
        try:
            return self.stack.pop()
        except IndexError as e:
            print('stack is empty')
    def __str__(self):
        return str(self.stack)

stack = Stack()     # 创建并初始化栈
stack.push(1)       # 整数 1 入栈
stack.push(2)       # 整数 2 入栈
print(stack)        #打印栈的内容
stack.pop()         # 整数 2 出栈
stack.pop()         # 整数 1 出栈
stack.pop()         # 出栈操作,但因为是空栈,提示 'stack is empty'

# 程序运行结果如下:
# [1, 2]
# stack is empty
stack.py

  

  2.2 deque 对象

    colletions.deque (双端队列)支持从任意一端增加和删除元素。

    deque 是线程安全,内存高校的队列,它被设计为从两端追加和弹出都非常快。

    构造函数如下:

deque([iterable[,maxlen]])    # 构造函数

    其中,可选的 iterable 为初始元素;maxlen 用于指定队列长度(默认无限制)。

deque 对象 dq 支持的方法如下表所示:

方法 说明
dq.append(x) 在右端添加元素 x
dq.appendleft(x) 在左端添加元素 x
dq.pop() 从右端弹出元素。没有则抛出 IndexError
dq.popleft() 从左端弹出元素。没有则抛出 IndexError
dq.extend(iterable) 在右端添加系列 iterable 中的元素
dq.extendleft(iterable) 在左端添加系列 iterable 中的元素
dq.remove(value) 移除第一个找到的 x ,没有则抛出 IndexError
dq.count() 返回元素 x 在队列中出现的个数
dq.clear() 删除所有元素,即清空队列
dq.reverse() 反转队列中所有元素
dq.rotate(n) 如果 n > 0 ,所有元素向右移动 n 个位置(循环);否则向左

deque 对象示例【读取文件,返回文件的最后 n 行内容】:

import collections

def tail(filename,n = 10):
    with open(filename) as f:
        return collections.deque(f,n)

path = r'deque_tail.py'
dq = tail(path,n = 2)
print(dq.popleft())
print(dq.popleft())

# 程序运行结果如下:
# print(dq.popleft())
#
# print(dq.popleft())
deque_tail.py

    

    2.3 deque 作为栈和队列

      deque 对象方法 append() 用于入栈操作;pop() 方法对应于出栈操作。

      deque 对象方法 append() 用于进队操作;popleft() 方法对应于出队操作。

deque 作为栈示例:

from collections import *

dq = deque()
dq.append(1);dq.append(2);dq.append(3)   # 整数 1,2,3 入栈
dq.pop();dq.pop();dq.pop()               # 整数 3,2,1 出栈
栈的示例

deque 作为队列示例:

from collections import *

dq = deque()
dq.append(1);dq.append(2);dq.append(3)   # 整数 1,2,3 入队
dq.popleft();dq.popleft();dq.popleft()               # 整数 3,2,1 出队
队的示例

 deque作为双向队列:

from collections import deque
dq = deque(range(10),maxlen=10)
print(dq)
dq.rotate(3)
# 队列的旋转操作接受一个参数 n ,当 n > 0 时,队列最右边的 n 个元素会被移动到队列的左边;
# 当n < 0 时,队列最左边的 n 个元素会被移动到右边。
print(dq)

dq.appendleft(-1)
# 当试图对一个已满(len(d) == d.maxlen)的队列做头部添加操作的时候,
# 它尾部的元素会被删除掉。注意在下一行里,元素 6 被删除了。
print(dq)

dq.extend([11,22,33])
# 在尾部添加三个元素的操作会挤掉 1-,7,8。
print(dq)

dq.extendleft([99,88,77])
# extendleft(iter) 方法会把迭代器里的元素逐个添加到双向队列的左边,
# 因此迭代器里的元素会逆序出现在队列中。
print(dq)

# 程序运行结果如下:
# deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], maxlen=10)
# deque([7, 8, 9, 0, 1, 2, 3, 4, 5, 6], maxlen=10)
# deque([-1, 7, 8, 9, 0, 1, 2, 3, 4, 5], maxlen=10)
# deque([9, 0, 1, 2, 3, 4, 5, 11, 22, 33], maxlen=10)
# deque([77, 88, 99, 9, 0, 1, 2, 3, 4, 5], maxlen=10)
双向队列

  双向队列除了实现大部分列表所拥有的放啊,也有一些额外的符合自身设计的方法。

  但是为了实现这些方法,双向队列也付出了一些代价,

  从队列中间删除元素的操作会慢一些,因为它只对在头尾的操作进行了优化。

  append 和 popleft 都是原子操作,也就是说 deque 可以在多线程程序中安全地当左先进先出的队列使用,

  而使用者不需要担心资源所 的问题。

  除了 deque 之外,还有其他的 python 标准库也有对队列的实现:http://www.cnblogs.com/HZY258/p/8562078.html

3. 集合

  集合数据类型是没有顺序的简单对象的聚集,且集合中元素不重复。python 集合数据类型包括可变集合对象(set)和不可变集合对象(frozenset)。

  

  3.1 集合的运算:并集,交集,差集和对称差集

集合运算如下表所示:

运算符 说明
s1|s2 ... 返回 s1,s2,...的并集
s1&s2& ... 返回 s1,s2,...的交集
s1-s2 返回 s1,s2,...的差集
s1^s2 返回 s1,s2, ...的对称差集

集合的对象方法如下表所示:

方法 说明
s1.isdisjoint(s2) 如果集合 s1 和 s2 没有共同元素,返回 True ,否则返回 False
s1.issubset(s2) 如果集合 s1 是 s2 的子集,返回 True,否则返回 False
s1.issuperset(s2) 如果集合 s1 是 s2 的超集,返回 True,否则返回 False
s1.union(s2, ...) 返回 s1,s2,...的并集
s1.intersection(s2,...) 返回 s1,s2,...的交集
s1.difference(s2,...) 返回 s1,s2,...的差集
s1.symmetric_difference(s2) 返回 s1 和 s2 的对称差集

  

  3.2 集合的比较运算;相等,子集和超集

集合支持如下表所示的比较运算:

运算符 说明 运算符 说明
 s1 = s2 s1和 s2的元素相同 s1 <= s2 s1是 s2的子集
s1 != s2 s1和 s2的元素不完全相同 s1 >= s2 s1是 s2的超集
s1 < s2 s1是 s2的纯子集 s1 > s2 s1是 s2的纯超集

  

 

 

 

 

  3.3 集合的长度,最大值,最小值,元素和

    通过内置函数 len(), max(), min(), sum(),可以获取集合的长度,元素最小值,元素最小值,元素之和。

    如果元素有非整数,则求和将导致 TypeError 异常。

4. 字典(映射)

  字典(dict , 或映射 map)是一组键/值队的数据结构。每个键对应于一个值。在字典中,键不能重复。根据键可以查询到值。

  

  4.1 对象的哈希值

    字典是键和值的映射关系。字典的键必须是可 hash 的对象,即实现了 __hash__() 的对象,

    一个对象的 hash 值也可以使用内置函数 hash() 获得。

    不可变对象是可 hash 对象;而可变对象通常是不可 hash 对象,因为不可变对象的内容可以改变,因而无法通过 hash() 函数获取其 hash 值。

    字典的键只能使用不可变的对象,但字典的值可以使用不可变或可变的对象。一般而言,应该使用简单的对象作为键。

  

  4.2 字典的视图对象

    字典 d 支持下列的视图对象,通过它们,可以动态访问字典中的数据。

      d.key()      # 返回字典 d 的键 key 的列表

      d.values()      # 返回字典 d 的值 value 的列表

      d.items()     # 返回字典 d 的键值(key ,value)队的列表

  4.3 字典对象的长度和比较

    通过内置函数 len(),可以获取字典的长度(元素个数)。

    虽然字典对象也支持内置函数 max() ,min() ,sum(),以计算字典 key,但没有太大意义。

    另外,字典对象也支持比较运算符(< ,<= ,== ,!= ,>= ,>),但只有 == ,!= 有意义。

5.collections 数据结构简介

http://www.cnblogs.com/HZY258/p/8537812.html

  

原文地址:https://www.cnblogs.com/HZY258/p/8522906.html