python 数据结构六 之 字典与集合

python数据结构教程第六课
本章是数据结构教程的最后一课,讲述python内部已经实现的字典与集合类

一、简介
二、字典与集合的抽象数据类型(ADT)
三、二叉排序树(字典类)的python实现

一、简介

数据的存储和访问是计算机最基本的功能。
字典就是支持基于关键码的数据结构存储与检索的数据结构,关键码(key)是检索时提供的信息。字典在实际使用中分为两类:
1)静态字典:在建立之后,这种字典的内容和结构都不在发生变化,主要操作只有检索
2)动态字典:在初始创建后,这种字典的内容(和结构)将一直处于动态变动之中,对于这种字典,除了检索之外,最重要的基本操作还包括数据项的插入和删除等。python内部的字典类型就是这种动态字典
在计算机领域,具体的数据项可以看作个体,数据项的汇集就是集合,python内部的集合类型有set与frozenset两种,其区别与静态字典和动态字典的区别类似,这里不再赘述

二、字典与集合的抽象数据类型(ADT)

这里分别给出字典与集合的抽象数据类型,还有python内部字典与集合的基本操作方法
1)字典的抽象数据类型

ADT DictDict(self)           #构造新字典
    is_empty(self)       #空字典判断
    num(self)            #返回元素个数
    search(self,key)     #返回key对应的值
    insert(self, key,value)  #插入新元素
    delete(self,key)     #删除键值对
    values(self)         #value迭代器
    entries(self)        #键值对迭代器

python里的字典类型,其基本操作如下:

a = {'a':11,'b':22,'c':44,'d':'asdf'}
b = {23:'a',43:'b',52:'c',12:'d'}
for i in a.items():
    print(i,end=' ')
print()
for i in b.items():
    print(i,end=' ')
print()
print(a)
print(b.get(23))
b.clear()
print(b)

输出结果:

('a', 11) ('b', 22) ('c', 44) ('d', 'asdf') 
(23, 'a') (43, 'b') (52, 'c') (12, 'd') 
{'a': 11, 'b': 22, 'c': 44, 'd': 'asdf'}
a
{}

这里要注意的是,字典类型有一个非常重要的数据不变式,那就是字典类型的键值是不允许改变的,因为字典的检索基于键值,一旦键值发生变化,会出现字典内部的混乱,python内部的字典类型也严格遵守这一规则,键值只能为不变类型,否则会报错

2)集合的抽象数据类型

ADT Set:
    Set(self)             #创建空集
    is_empty(self)        #空集判断
    member(self,elem)     #判断elem是否在集合内
    insert(self,elem)     #插入元素
    delete(self,elem)     #删除元素
    intersection(self,oset)   #求交集
    union(self,oset)      #求并集
    different(self,oset)  #集合相减
    subset(self,oset)     #判断本集合是否是oset的子集

python里的set类型,其常用操作如下:

a = set([11,34,'sd',535,6547,3,7,'fd',2,757,4])
b = set([11,34,'ew','!'])
print(a)
print(b)
a -= b
print(a)
b.clear()
print(b)
c = a.copy()
c.pop()
c.pop()
print(c)
print(a)

测试结果:

{'sd', 34, 3, 2, 4, 7, 11, 'fd', 6547, 757, 535}
{'ew', 34, 11, '!'}
{'sd', 3, 2, 4, 7, 'fd', 6547, 757, 535}
set()
{3, 4, 7, 'fd', 6547, 535, 757}
{'sd', 3, 2, 4, 7, 'fd', 6547, 757, 535}

三、二叉排序树(字典类)的python实现

python里已经有了较为完整的字典与集合类型,读者们只需要使用即可,这里给出字典类的二叉树排序实现,相比于普通的字典类,可以提升搜索效率

#关联对象的类Assoc,用于存储键值对
class Assoc:
    def __init__(self,key,value):
        self.key = key
        self.value = value

    def __lt__(self,other):
        return self.key < other.key

    def __le__(self,other):
        return self.key < other.key or self.key == other.key

    def __str__(self):
        return "Assoc({0},{1})".format(self.key,self.value)

import BNode     #请参考链表或者树章节的博客

#二叉排序树(字典类)
class DictBTree:
    def __init__(self):
        self._root = None

    def is_empty(self):
        return self._root is None

    def search(self,key):
        bt = self._root
        while bt is not None:
            entry = bt.data()
            if key < entry.key:
                bt = bt.left()
            elif key > entry.key:
                bt = bt.right()
            else:
                return entry.value
        return None

    def insert(self,key,value):
        bt = self._root
        if bt is None:
            self._root = BNode(Assoc(key,value))
            return
        while True:
            entry = bt.data()
            if key < entry.key:
                if bt.left() is None:
                    bt.set_left(BNode(Assoc(key,value))) 
                    return
                bt = bt.left()
            elif key > entry.key:
                if bt.right() is None:
                    bt.set_right(BNode(Assoc(key,value))) 
                    return
                bt = bt.right()
            else:
                bt.data().value = value
                return

    #迭代器
    def entries(self):
        t,s = self._root,SStack()
        while t is not None or not s.is_empty():
            while t is not None:
                s.push(t)
                t = t.left()
            t = s.pop()
            yield (t.data().key,t.data().value)
            t= t.right()

    def delete(self,key):
        p,q = None,self._root
        while q is not None and q.data().key != key:
            p = q
            if key < q.data().key:
                q = q.left()
            else:
                q = q.right()
            if q is None:
                return

            if q.left() is None:
                if p is None:
                    self._root = q.right()
                elif q is p.left:
                    p.set_left(q.right()) 
                else:
                    p.set_right(q.right()) 
                return

            r = q.left()
            while r.right() is not None:
                r = r.right()
            r.set_right(q.right())
            if p is None:
                self._root = q.left
            elif p.left is q:
                p.set_left(q.left) 
            else:
                p.set_right(q.left)

    def print(self):
        for k,v in self.entries():
            print(k,v)

def build_dictBTree(entries):
    dic = DictBTree()
    for k,v in entries:
        dic.insert(k,v)
    return dic

测试程序:

entry = [('a','1'),('b','2'),('c','3')]
diction = build_dictBTree(entry)
diction.print()
diction.delete('b')
diction.print()

结果:

a 1
b 2
c 3
a 1
c 3
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Liangjun_Feng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值