简体   繁体   中英

Binary Trees in Python

I have to implement a binary tree in Python. One node of a tree have several attributes. One of my requirements is a minimum of memory usage, specifically the overhead of the data structures.

So my question is, how much overhead is produced by different ways of the implementation. I think about using a dictionary where one key is "left" and another is "right" for the child nodes. Another way would be by using a class with the attributes "left" and "right" for the children.

Are there any noticable advantages or disadvantages for these two options? Or are there any better options?

I'll have to use Pythons standard library and I'm using Python 3.5.

Python dicts are heavy, memory-wise. A class that doesn't require dynamic attributes can be comparitively light-weight if you take advantages of __slots__ :

By default, instances of classes have a dictionary for attribute storage. This wastes space for objects having very few instance variables. The space consumption can become acute when creating large numbers of instances.

The default can be overridden by defining __slots__ in a class definition. The __slots__ declaration takes a sequence of instance variables and reserves just enough space in each instance to hold a value for each variable. Space is saved because __dict__ is not created for each instance.

Consider:

In [1]: class Node(object):
   ...:     __slots__ = ('left', 'right','data')
   ...:     def __init__(self, left, right, data):
   ...:         self.left = left
   ...:         self.right = right
   ...:         self.data = data
   ...:

In [2]: n = Node(None, None, None)

In [3]: d = {}

In [4]: import sys

In [5]: sys.getsizeof(n)
Out[5]: 64

In [6]: sys.getsizeof(d)
Out[6]: 288

I think you can use class, dictionary, and namedtuple to implement it.

if you want to use class:

class BNode(object):
    def __init__(self, val):
        self.val = val
        self.left = None
        self.right = None

import sys
b = BNode(5)
sys.getsizeof(b)

This will return 56 on my PC with python 3.5.2. If we want to optimize it, we add __slot__ atrribute.

class BNode(object):
    __slot__ = ('val','left','right')
    def __init__(self, val):
        self.val = val
        self.left = None
        self.right = None

b = BNode(5)

This will also return 56 on my PC.

If you want to use dictionary:

node_dict = {'left':None, 'right':None, 'val':5}
sys.getsizeof(node_dict)

this will return 288 on my PC.

There is another option: using namedtuple

from collections import namedtuple
BNode = namedtuple('BNode', ['val','left','right'])
b = BNode(5, None, None)
sys.getsizeof(b)

this will return 76 on my PC.

According to the code above, I think we should use __slot__ with class to implement your code for considerating memeory limitation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM