Data structure __ heap implements priority queue, several traversal of binary tree, priority queue implements Huffman tree

prospect

I finished learning the binary tree part before, and I will sort it out today, probably these small pieces

  • List-based stack and queue
  • Recursive traversal of binary tree, BFS, three kinds of DFS
  • Heap-based (complete binary tree) priority queue implementation
  • Priority queue implementation of HaffMan tree

Stack

class Stack:
    def __init__(self):
        self._elems = []

    def push(self, item):
        self._elems.append(item)

    def pop(self):
        return self._elems.pop()

    def top(self):
        return self._elems[-1]

    def is_empty(self):
        return len(self._elems) == 0

Queue

class UnBlockingQueue:
    def __init__(self):
        self._elems = []

    def enqueue(self, item):
        self._elems.append(item)

    def ququue(self):
        return self._elems.pop(0)

    def head(self):
        return self._elems[0]

    def is_empty(self):
        return len(self._elems) == 0

binary tree

from 数据结构与算法.Stack import Stack
from 数据结构与算法.UnBlockingQueue import UnBlockingQueue as Queue


# 二叉数节点
class Node(object):
    def __init__(self, data, left, right):
        self.data = data
        self.left = left
        self.right = right


class Tree(object):

    def __init__(self, data):
        self.root = Node(data, None, None)

    # 队列实现BFS 广度优先遍历
    def bfs(self, root):
        queue = Queue()
        queue.enqueue(root)
        while not queue.is_empty():
            root = queue.ququue()
            print(root.data)
            if root.left is not None:
                queue.enqueue(root.left)
            if root.right is not None:
                queue.enqueue(root.right)

    # 递归实现先序遍历
    def xianxu(self,root):
        if root:
            print(root.data)
            self.xianxu(root.left)
            self.xianxu(root.right)

    # 递归实现后续遍历
    def houxu(self,root):
        if root:
            self.houxu(root.left)
            self.houxu(root.right)
            print(root.data)

    # 递归实现中序遍历
    def zhongxu(self,root):
        if root:
            self.zhongxu(root.left)
            print(root.data)
            self.zhongxu(root.right)

    # stack 实现先序深度优先遍历
    def NFS_xianxu(self, root):
        stack = Stack()
        stack.push(root)
        while not stack.is_empty():
            while root is not None:
                print(root.data)
                stack.push(root.right)
                root = root.left
            root = stack.pop()

    # stack 实现中序深度优先遍历
    def NFS_zhongxu(self, root):
        stack = Stack()
        while not stack.is_empty() or root is not None:
            while root is not None:
                stack.push(root)
                root = root.left
            if not stack.is_empty():
                root = stack.pop()
                print(root.data)
                root = root.right

    # stack 实现后序深度优先遍历
    def NFS_houxu(self, root):
        stack = Stack()
        while not stack.is_empty() or root is not None:
            while root is not None:
                stack.push(root)
                if root.left is not None:
                    root = root.left
                else:
                    root = root.right
            root = stack.pop()
            print(root.data)
            if not stack.is_empty() and root is stack.top().left :
                root = stack.top().right
            else:
                root = None

    # 另一种栈实现后序DFS的算法,简单些
    def DFS_2houxu(self):
        if self.root is None:
            return
        else:
            stack1 = []
            stack2 = []
            stack1.append(self.root)
            # 对每一个头结点进行判断,先将该头结点放到栈2中,如果该节点有左子树则放入栈1, 有右子树也放到栈1
            while stack1:
                current = stack1.pop()
                stack2.append(current)
                if current.left:
                    stack1.append(current.left)
                if current.right:
                    stack1.append(current.right)
            # 直接遍历输出stack2即可
            while stack2:
                print(stack2.pop().data)

    def bfs2(root):
        queue = Queue()
        queue.enqueue(root)
        while not queue.is_empty():
            root = queue.ququue()
            print(root.data)
            if root.left is not None:
                queue.enqueue(root.left)
            if root.right is not None:
                queue.enqueue(root.right)


if __name__ == '__main__':
    tree = Tree(1)
    tree.root.left = Node(2, None, None)
    tree.root.right = Node(3, None, None)
    tree.root.left.left = Node(4, None, None)
    tree.root.left.right = Node(5, None, None)
    tree.root.right.left = Node(6, None, None)
    tree.root.right.right = Node(7, None, None)
    tree.root.left.left.left = Node(8, None, None)
    tree.root.left.left.right = Node(9, None, None)
    tree.root.right.right.right = Node(10, None, None)
    print('\n宽度优先算法')
    tree.bfs(tree.root)
    print('\n先序NFS算法')
    tree.NFS_xianxu(tree.root)
    print('\n中序NFS算法')
    tree.NFS_zhongxu(tree.root)
    print('\n后序NFS算法')
    tree.NFS_houxu(tree.root)

Priority queue heap implementation

class PriorityQueue:
    def __init__(self, elems=[]):
        self._elems = elems
        if elems:
            self.buildheap()

    # 向上筛选,从最后一个节点向上和它的父节点比较,小的上移
    # 参数:
    #   e:代表需要进行比较的元素
    #   last:代表列表的最后一个index
    def siftup(self, e, last):
        elems, i , parent = self._elems, last, (last-1)//2
        # 如果父节点比e大,将父节点下移,i位置始终存放较小的那个最终的结果
        while i > 0 and e < elems[parent]:
            elems[i] = elems[parent]
            # 将i,parent依次上移
            i, parent = parent, (parent-1)//2
        elems[i] = e

    # 向下筛选,从最上面的一个节点向下和它的两个子节点进行比较
    # 参数:
    #   e:代表需要比较的元素
    #   start:代表从哪个索引位置开始比较
    #   end:代表结束的索引
    def siftdown(self, e, start, end):
        elems, i, child = self._elems, start, 2*start+1
        while child < end:
            // 角逐出子节点中较小的那一个
            if child+1 < end and elems[child+1] < elems[child]:
                child += 1
            if e < elems[child]:
                break
            # 如果子节点的值小于父节点,子节点上移
            elems[i] = elems[child]
            # 位置向上移动
            i, child = child, 2*child+1
        elems[i] = e

    def enqueue(self, e):
        self._elems.append(None)
        self.siftup(e, len(self._elems)-1)

    def ququeue(self):
        e0 = self._elems[0]
        e = self._elems.pop()
        if len(self._elems) > 0:
            self.siftdown(e, 0, len(self._elems))
        return e0

    def buildheap(self):
        end = len(self._elems)
        for i in range(end//2, -1, -1):
            self.siftdown(self._elems[i], i, end)

    def print(self):
        print(self._elems)

    def get_number(self):
        return len(self._elems)

if __name__ == '__main__':
    queue = PriorityQueue()
    queue.enqueue(10)
    queue.enqueue(2)
    queue.print()
    queue = PriorityQueue([10, 2, 1, 6])
    queue.print()

I checked the implementation of the priority queue in the library. It is also based on the heap. The ideas are similar. The implementation of the heap is relatively unfamiliar to the implementation of the binary tree. It needs to be understood a few times. If you are a beginner, I suggest you go to Search the Internet for a detailed explanation of this part.

HaffManTree

from 数据结构与算法.二叉树 import Node,Tree
from 数据结构与算法.PriorityQueue import PriorityQueue

class HaffManTreeNode(Node):

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

# 代表节点的权值
weights = [2, 2, 5, 10, 4, 3, 7]


def haffman(weights):
    queue = PriorityQueue()
    for w in weights:
        queue.enqueue(HaffManTreeNode(w, None, None))
    # 从队列中取出前两个组合成新节点加入队列
    while queue.get_number() > 1:
        t1 = queue.ququeue()
        t2 = queue.ququeue()
        new = HaffManTreeNode(t1.data+t2.data, t1, t2)
        queue.enqueue(new)
    result = queue.ququeue()
    return result

if __name__=='__main__':
    root = haffman(weights)
    Tree.bfs2(root)

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324574905&siteId=291194637