图数据结构

在这里插入图片描述
1.邻接集合

# 将节点的编号赋值给相应的节点,方便操作
a, b, c, d, e, f, g, h = range(8)
N = [{'b', 'c', 'd', 'e', 'f'},
     {'c', 'e'},
     {'d'},
     {'e'},
     {'f'},
     {'c', 'g', 'h'},
     {'f', 'h'},
     {'f', 'g'}]
列表中每个集合是每个节点邻接点集
在python2.7中,set([1,3])这样表示,set()表示空集合.
在python3之后的版中,set{1,3}表示集合,空集合仍用set()表示.

#查看a的邻接节点有哪些
N[a]

2
{'b', 'c', 'd', 'e', 'f'}

# 检查g是否为a的一个邻接节点
'g' in N[a]

2
False

# 节点a的度
len(N[a])

2.邻接列表

# 表示同一个图
a, b, c, d, e, f, g, h = range(8)
N = [ ['b', 'c', 'd', 'e', 'f'],
      ['c', 'e'],
      ['d'],
      ['e'],
      ['f'],
      ['c', 'g', 'h'],
      ['f', 'h'],
      ['f', 'g'] ]
# 邻接列表表示图结构,与邻接集合的操作相同

'g' in N[a]
1
False
1
len(N[a])
 5
3.邻接字典

上面的两种表示方法,没有表示出与邻居节点之间的关联性
邻接字典,用dict类型替代set()和list,用键值对表示每一个邻接节点

a, b, c, d, e, f, g, h = range(8)
N = [{'b':2, 'c':1, 'd':3, 'e':9, 'f':4},
     {'c':4, 'e':3},
     {'d':8},
     {'e':7},
     {'f':5},
     {'c':2, 'g':2, 'h':2},
     {'f':1, 'h':6},
     {'f':9, 'g':8}]

'e' in N[a]

True

len(N[b])

# 边的权值
N[a]['c']

2

嵌套字典

# 以上三种图的表示,都是使用了list类型
# 下面使用嵌套的字典结构
N = {'a':{'b':2, 'c':1, 'd':3, 'e':9, 'f':4},
     'b':{'c':4, 'e':3},
     'c':{'d':8},
     'd':{'e':7},
     'e':{'f':5},
     'f':{'c':2, 'g':2, 'h':2},
     'g':{'f':1, 'h':6},
     'h':{'f':9, 'g':8}}

'f' in N['e']

True

len(N['e'])


# a,e之间链接权值
N['a']['e']

# 邻接集的字典表示
N = {'a':set('bcdef'),
     'b':set('ce'),
     'c':set('d'),
     'd':set('e'),
     'e':set('f'),
     'f':set('cgh'),
     'g':set('fh'),
     'h':set('fg')}
# 如果省略set()构造器,用邻接字符串表示键值,工作方式相当于邻接列表

'h' in N['a']

False

len(N['g'])

 
4.邻接矩阵

# 邻接矩阵,通过一个二维数组,对应图中的每个节点,使用0,1来表示相关节点是否为当前节点的邻居
# 可以使用嵌套list实现
a, b, c, d, e, f, g, h = range(8)

N = [[0, 1, 1, 1, 1, 1, 0, 0],
     [0, 0, 1, 0, 1, 0, 0, 0],
     [0, 0, 0, 1, 0, 0, 0, 0],
     [0, 0, 0, 0, 1, 0, 0, 0],
     [0, 0, 0, 0, 0, 1, 0, 0],
     [0, 0, 1, 0, 0, 0, 1, 1],
     [0, 0, 0, 0, 0, 1, 0, 1],
     [0, 0, 0, 0, 0, 1, 1, 0]]

# 检查a, b是否为相邻节点,即检查N[a][b]是否为1
N[a][b] == 1

True

# c节点的度
sum(N[c])

# 扩展邻接矩阵,实现一个没有自循环,对边加权
# 无自循环状态,对角线元素全部为0
# 加权,用权值替换真值
# 将不存在的边设置一个去穷大的权值(float('inf')),或None

a, b, c, d, e, f, g, h = range(8)
inf = float('inf')

N = [[  0,   2,   1,   3,   9,   4, inf, inf],
     [inf,   0,   4, inf,   3, inf, inf, inf],
     [inf, inf,   0,   8, inf, inf, inf, inf],
     [inf, inf, inf,   0,   7, inf, inf, inf],
     [inf, inf, inf, inf,   0,   5, inf, inf],
     [inf, inf,   2, inf, inf,   0,   2,   2],
     [inf, inf, inf, inf, inf,   1,   0,   6],
     [inf, inf, inf, inf, inf,   9,   8,   0]]

# 检查a,b是否互为相邻节点,只要邻接权值不是无穷大
N[a][b] < inf

True

# a节点的度
# -1是因为对角线元素,要除去
sum(1 for w in N[a] if w < inf) - 1

在python的第三方库中也提供了实现数组,矩阵的方法,Numpy,sicpy,scipy还支持稀疏矩阵实现,节省内存

------------------------------------------------------------------------------
1
树的表示
# 使用嵌套列表实现带根的树结构
# 将各个子树组织成一个子树列表
T = [['a', 'b'], ['c'], ['d',['e', 'f']]]

树的结构如下

在这里插入图片描述

T[0][1]

'b'

T[2][0]

'd'

1.二叉树

class Tree:
    def __init__(self, left, right):
        self.left = left
        self.right = right

#创建类的实例
t = Tree(Tree('a', 'b'), Tree('c', 'd'))

# 访问左子树的叶子节点
t.left.right

'b'

多路搜索时

class Tree:
    def __init__(self, kids, next=None):
        self.kids = self.vlaue = kids
        self.next = next

# 属性value只是为kids提供了一个更具描述性的名称,相当与别名
t = Tree(Tree('a', Tree('b', Tree('c', Tree('d')))))
t.vlaue.next.next.vlaue

'c'

t.kids.next.next.vlaue
1
'c'
1
使用Bunch模式实现树形结构

# bunch的实现方式有多种,下面是其中的一种
class Bunch(dict):
    def __init__(self, *args, **kwds):
        super().__init__(*args, **kwds)
        self.dict = self
# 模式从字典类继承,所以有些与字典相同的操作

例
x = Bunch(name = 'JingHui', age = 23)
x['name']

'JingHui'

# 树实例
T = Bunch
t = T(left = T(left = 'a', right = 'b'), right = T(left = 'c', right = T(left = 'd', right = 'e')))

# 左子树
t['left']

{'left': 'a', 'right': 'b'}

# 左子树左叶子节点
t['left']['left']

'a'

# 右子树是否存在左子节点
'left' in t['right']

True

t['right']['right']['left']

'd'
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值