01:数据结构和算法

Posted 情愿为你,画地为牢。

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了01:数据结构和算法相关的知识,希望对你有一定的参考价值。

*** :“_” 占位变量 (须保证你选用的那些占位变量名在其他地方没被使用到,一般选用 "_")

  data = [ \'ACME\', 50, 91.1, (2012, 12, 21) ]

   _, shares, price, _ = data


*** : 解压变量 *para

  *trailing, current = [10, 8, 7, 1, 9, 5, 10, 3]#该方法需要保证current能获取到一个值(python3适用)


*** : collections python 容器数据类型

  ----Counter是对字典的型的补充,它继承了dict类,用于追踪迭代项出现次数。

    para = [\'home\', \'dir\', \'cmd\', \'home\', \'list\',\'dir\']

    res = Counter(para)   #Counter({\'home\': 2, \'dir\': 2, \'cmd\': 1, \'list\': 1})
    res 具有字典的一切特效,同时还具有特别的特性

    list(res.elements())   #[\'home\', \'home\', \'cmd\', \'list\', \'dir\', \'dir\']
    res.most_common(3)  # [(\'home\', 2), (\'dir\', 2), (\'cmd\', 1)]

    new = Counter([\'home\'])   

    res.substract(new)#同res - new。    #结果Counter({\'dir\': 2, \'home\': 1, \'cmd\': 1, \'list\': 1})

  ----OrderedDict 能够记录字典元素插入的顺序,常常和排序函数一起使用来生成一个排序的字典。()

    res = {‘banana’:3,’apple’:4,’pear’:1,’orange’:2}

    OrderedDict(sorted(d.items(),key = lambda t:t[0]))#字典安装先后生成顺序

    
  ----defaultdict属于内建函数dict的一个子类,python自动的为它的键赋了一个初始化值

    dic = defaultdict(int) #表示用一个int()函数作为参数出给defaultdict,我们不带参数调用int(),int()就会返回一个0值

   dic[\'value\'] += 1#不会报错

 ---- ChainMap  接受多个字典并将它们在逻辑上变为一个字典。(并不是真正合并成一个字典)
   c = ChainMap(a,b)
   两个字典中执行查找操作是:先从 a 中找,如果找不到再在 b 中找。


 ----
deque   deque是双端队列,可以从两端塞元素进去,也可以从两端取元素;  deque是线程安全的,可以用来做多线程的共享资源
   res = deque([1,2,3,2,4])
   #双端操作,同列表。append/appendleft, extend/extendleft(其实如同一个元素使用append或者appendleft),pop/popleft,remove/reverse
   rotate :  #res.rotate(-2)  从右往左旋转 此时 res = deque([3,2,4,1,2])
   
   res = deque([1,2,3,4,5,6,7], maxlen=4) #res = deque([4,5,6,7])  #表示定长为4的队列

 ---- namedtuple 命名元组命。名元组另一个用途就是作为字典的替代
   如果你需要构建一个非常大的包含字典的数据结构,那么使用命名元组会更加高效。 但是需要注意的是,不像字典那样,一个命名元组是不可更改的。
   如果你真的需要改变然后的属性,那么可以使用命名元组实例的 _replace() 方法, 它会创建一个全新的命名元组并将对应的字段用新的值取代。
   如果你的目标是定义一个需要更新很多实例属性的高效数据结构,这时候你应该考虑定义一个包含 __slots__ 方法的类

   person = namedtuple(\'P\', \'name age gender\')或者 person = namedtuple(\'P\', [\'name\', \'age\', \'sex\'])
   obj = person(name = \'holen\', age = 25, sex = \'male\')或者obj = person(\'holen\', 25, \'male\')#类似python种对象的使用
   obj = obj._replace(age=75)#改变命名元组的值
   使用namedtuple时候,不能使用关键字。同时,字串或者列表的值不能重复。
   可以使用如下的保证:
   person = namedtuple(\'P\', \'name age gender age\', rename=True)
   此时查看person._fields # name, age, gender, _3 _3表示索引位置为3的元素已经重复

*** : heapq 堆数据结构
  堆数据结构最重要的特征是 iterable[0] 永远是最小的元素。
   ---- heapq.nlargest(n, iterable[, key])/heapq.nsmallest(n, iterable[, key])
    (从迭代器对象iterable中返回前n个最大/小的元素列表,key用于匹配是字典对象的iterable,用于更复杂的数据结构中。)
    如果n的大小和集合大小接近的时候,效率不如sort.
  ---- heapq.heapify(iterable)         #将iterable转换成堆. iterable 为定义的堆,无返回值。
  ---- headpq.pop(iterable)           #先将第一个元素弹出来,然后用下一个最小的元素来取代被弹出元素
  ---- heapq.heappush(iterable,item)      #iterable为定义堆,item 增加的元素.
  ---- heapq.heapreplace(iterable, item)     #删除最小元素值,添加新的元素值
  ---- heapq.heappushpop(iterable, item)     #首判断添加元素值与堆的第一个元素值对比,如果大于则删除最小元素,然后添加新的元素值,否则不更改堆
  ---- heapq.merge(iterable, iterable1)      #将多个堆合并,返回一个合并后的迭代
  ---- izip, imap, islice, tee
  
import heapq
#优先队列
#在上面代码中,队列包含了一个 (-priority, index, item) 的元组。 优先级为负数的目的是使得元素按照优先级从高到低排序。 这个跟普通的按优先级从低到高排序的堆排序恰巧相反。
#index 变量的作用是保证同等优先级元素的正确排序。 通过保存一个不断增加的 index 下标变量,可以确保元素按照它们插入的顺序排序。 而且, index 变量也在相同优先级元素比较的时候起到重要作用。

class PriorityQueue:
    def __init__(self):
        self._queue = []
        self._index = 0

    def push(self, item, priority):
        heapq.heappush(self._queue, (-priority, self._index, item))
        self._index += 1

    def pop(self):
        return heapq.heappop(self._queue)[-1]
View Code

*** :  列表去重(保持原来顺序)
#1
def dedupe(items):
    seen = set()
    for item in items:
        if item not in seen:
            yield item
            seen.add(item)

a = [1, 5, 2, 1, 9, 1, 5, 10]
list(dedupe(a)) #[1, 5, 2, 9, 10]

#2
OrderedDict.fromkeys(a).keys()

#3
seen = set()
 seen_add = seen.add
[x for x in a if not (x in seen or seen_add(x))]
View Code

*** :  slice 切片对象
  ---内置的 slice() 函数创建了一个切片对象,可以被用在任何切片允许使用的地方。
    一个切片对象a,你可以分别调用它的 a.start , a.stop , a.step 属性
    a = [1,2,3,4,5,6,7]
    s = slice(3,50)
    a[s] #同a[3:50]
    s.indices(len(a)) #-->所有值都会被合适的缩小以满足边界限制返回slice(3, 7, 1)该方法将它映射到一个确定大小的序列上, 返回一个三元组 (start, stop, step)
*** :  根据某个或某几个迭代项的字段来排序这个迭代
   ---operator 模块的 itemgetter
    res = sorted(rows, key=itemgetter(value[,value1]))# 如果迭代项是元组或者列表,value填索引,如果迭代项是字典,value填键值。

*** itertools模块
  ----
chain(iter1, iter2, ..., iterN):创建一个新迭代器来将所有的迭代器链接起来,返回从iter1持续到iterN的迭代器
  ----
chain.from_iterable(iterables): 一个备用链构造函数,其中的iterables是一个迭代变量,生成迭代序列
      
a = [[1, 2], [3, 4], [5, 6]]

      list(itertools.chain.from_iterable(a))   #[1, 2, 3, 4, 5, 6]
  ---- combinations(iterable, r):  #组合
  ---- permutations(iterable [,r]):   #排列
  ---- count([n]):创建一个迭代器,生成从n开始的连续整数,如果忽略n,则从0开始计算  
  ----cycle(iterable):创建一个迭代器,对iterable中的元素反复执行循环操作,内部会生成iterable中的元素的一个副本,此副本用于返回循环中的重复项。

  ---- tee(iterable [, n]): 从 iterable创建n个独立的迭代器,创建的迭代器以n元组的形式返回,n的默认值为2,此函数适用于任何可迭代的对象,但是,为了克隆原始迭代器,生成的项会被缓存,并在所有新创建的迭代器中使用,一定要注意,不要在调用tee()之后使用原始迭代器iterable,否则缓存机制可能无法正确工作。
  ---- dropwhile(predicate, iterable):给它传递一个函数对象和一个可迭代对象。 它会返回一个迭代器对象,丢弃原有序列中直到函数返回True之前的所有元素,然后返回后面所有元素。

  ---- takewhile(predicate [, iterable]): 生成iterable中predicate(item)为True的项,只要predicate计算为False,迭代就会立即停止。
  ---- starmap(func [, iterable]):生成值func(*item),其中item来自iterable,只有当iterable生成的项适用于这种调用函数的方式时,此函数才有效。
      starmap(pow, [(2,5), (3,2), (10,3)]) --> 32 9 1000

  ---- repeat(object [,times]):创建一个迭代器,重复生成object,times(如果已提供)指定重复计数,如果未提供times,将无止尽返回该对象。
      repeat(10, 3) --> 10 10 10

  ---- product(iter1, iter2, ... iterN, [repeat=1]):生成item1,item2等中的项目的笛卡尔积的元组,repeat是一个关键字参数,指定重复生成序列的次数
      product(\'ABCD\', \'xy\') --> Ax Ay Bx By Cx Cy Dx Dy
      product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111
  ----1):ifilter:同filter  #ifilterfalse: 仅生成iterable中为False的项
  ----2):izip:同zip     #
izip_longest(iter1,... iterN, [fillvalue=None]):迭代过程会持续到所有输入迭代变量iter1,iter2等都耗尽为止,如果没有使用fillvalue关键字参数指定不同的值,则使用None来填充已经使用的迭代变量的值。

  ----3)imap:  只要提供的一个迭代器不再生成值,迭代就会停止(例:list(imap(pow, (2,3,10), (5,2))) -->32,9)  不同map
  ----4)islice 如果你已经明确知道了要跳过的元素的个数的话,那么可以使用 islice()
      islice(items, 3, None) 同 items[3:]


注意:{key:value for key,value in b.items()} 这种方式生成字典比dict((key, value) for key, value in b.items())慢

*** python 聚集函数
  ---- 执行聚集函数(比如 sum() , min() , max()) 一个非常优雅的方式去结合数据计算与转换就是使用一个生成器表达式参数。

*** translate()、 maketrans()
  ---- sting.maketrans(\'123\', \'abc\') #建立映射表,将字符串中含有的\'1\',\'2\',\'3\'替换为\'a\',\'b\',\'c\'。 maketrans在string库中或者是字符串的方法中
   \'123456\'.translate(map) #用创建的映射表map转换字符串 输出 abc456
   
   translate有两个参数,第二个参数可选。表示指定需要删除的字符。
   allchars = string.maketrans(\'\', \'\')#所有的字符映射集
   delchars = allchars.translate(allchars, keep)#keep表示需要保留的字串,生成补集
   \'123456\'.translate(allchars, delchars)
     对于简单的替换操作, str.replace() 方法通常是最快的。如果你需要执行任何复杂字符对字符的重新映射或者删除操作的话, tanslate() 方法会非常的快。 

*** yield from 语句的递归生成器
from collections import Iterable
#isinstance(x, Iterable) 检查某个元素是否是可迭代的。 如果是, yield from 就会返回所有子例程的值。最终返回结果就是一个没有嵌套的简单序列
#额外的参数 ignore_types 和检测语句 isinstance(x, ignore_types) 用来将字符串和字节排除在可迭代对象外,防止将它们再展开成单个的字符。

def flatten(items, ignore_types=(str, bytes)):
    for x in items:
        if isinstance(x, Iterable) and not isinstance(x, ignore_types):
            yield from flatten(x)
        else:
            yield x

items = [1, 2, [3, 4, [5, 6], 7], 8]
# Produces 1 2 3 4 5 6 7 8
for x in flatten(items):
    print(x)

#语句 yield from 在你想在生成器中调用其他生成器作为子例程的时候非常有用。 如果你不使用它的话,那么就必须写额外的 for 循环了。
def flatten(items, ignore_types=(str, bytes)):
    for x in items:
        if isinstance(x, Iterable) and not isinstance(x, ignore_types):
            for i in flatten(x):
                yield i
        else:
            yield x
View Code

*** iter 函数

  iter 函数一个鲜为人知的特性是它接受一个可选的 callable 对象和一个标记(结尾)值作为输入参数。 当以这种方式使用的时候,它会创建一个迭代器, 这个迭代器会不断调用 callable 对象直到返回值和标记值相等为止。

from functools import partial

RECORD_SIZE = 32

with open(\'somefile.data\', \'rb\') as f:
    records = iter(partial(f.read, RECORD_SIZE), b\'\')
    for r in records:
        ...
View Code

 

*** : tempfile 你需要在程序执行时创建一个临时文件或目录,并希望使用完之后可以自动销毁掉

  ---- TemporaryFile() 、NamedTemporaryFile() 和 TemporaryDirectory() 函数 应该是处理临时文件目录的最简单的方式了,因为它们会自动处理所有的创建和清理步骤。

 



 

 

 
 

以上是关于01:数据结构和算法的主要内容,如果未能解决你的问题,请参考以下文章

以下代码片段的算法复杂度

可以解密加密数据的片段吗?

19 01 11 javascript ?????????????????????(???????????????) ??????????????????????????????(代码片段

片段之间的共享数据(父列表视图和子列表视图)

[linux][c/c++]代码片段01

为啥此代码片段返回意外结果?