선주문, 중간 주문 및 주문 후 큐 이진 트리

바이너리 트리에 큐를 지정해야하는 이유

먼저 질문을 봅시다

시퀀스 {1, 3, 6, 8, 10, 14}를 이진 트리로 구성합니다. n + 1 = 7

문제 분석 :

1. 위의 이진 트리를 순서대로 순회하면 숫자 시퀀스는 {8, 3, 10, 1, 6, 14}입니다.

2. 그러나 노드 6, 8, 10, 14의 왼쪽 및 오른쪽 포인터는 완전히 활용되지 않습니다.

3. 각 노드가 자신의 전면 및 후면 노드를 가리킬 수 있도록 각 노드의 왼쪽 및 오른쪽 포인터를 최대한 활용하려면 어떻게해야합니까?

4. 솔루션 단서 이진 트리

스레드 이진 트리에 대한 기본 소개

1. n 개 노드의 이진 연결 목록은 n + 1 [공식 2n- (n-1) = n + 1] 널 포인터 필드를 포함합니다. 이진 링크 목록의 널 포인터 필드를 사용하여 특정 순회 순서로 노드의 선행 노드와 후속 노드에 대한 포인터를 저장합니다 (이러한 종류의 추가 포인터를 "단서"라고 함).

2. 단서가있는 이진 연결 목록을 스레드 연결 목록이라고하고 해당 이진 트리를 스레드 이진 트리라고합니다. 단서의 특성에 따라 단서 바이너리 트리는 사전 주문 단서 바이너리 트리, 중간 주문 단서 바이너리 트리, 후순위 단서 바이너리 트리의 세 가지 유형으로 나눌 수 있습니다.

3. 노드의 이전 노드를 선행 노드라고하고 노드의 다음 노드를 후속 노드라고합니다.

노드 생성

class HeroNode {
    private int no;
    private String name;
    private HeroNode left;
    private HeroNode right;
    private HeroNode parent;
    //true 表示是线索化节点
    //false 表示不是线索化节点
    private boolean ThreadedLeft = false;
    private boolean ThreadedRight = false;

    public HeroNode(int no, String name) {
        this.no = no;
        this.name = name;
    }

    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public HeroNode getLeft() {
        return left;
    }

    public void setLeft(HeroNode left) {
        this.left = left;
    }

    public HeroNode getRight() {
        return right;
    }

    public void setRight(HeroNode right) {
        this.right = right;
    }

    public HeroNode getParent() {
        return parent;
    }

    public void setParent(HeroNode parent) {
        this.parent = parent;
    }

    public boolean isThreadedLeft() {
        return ThreadedLeft;
    }

    public void setThreadedLeft(boolean threadedLeft) {
        ThreadedLeft = threadedLeft;
    }

    public boolean isThreadedRight() {
        return ThreadedRight;
    }

    public void setThreadedRight(boolean threadedRight) {
        ThreadedRight = threadedRight;
    }

    @Override
    public String toString() {
        return "HeroNode{" +
                "no=" + no +
                ", name='" + name + '\'' +
                '}';
    }
}

순차 스레드 이진 트리

애플리케이션 사례 설명 : 다음 이진 트리를 순서대로 단서 이진 트리로 가져갑니다. 중간 순서 순회 순서는 {8, 3, 10, 1, 14, 6}입니다.

설명 : 2 진 트리가 스레드 될 때 노드 노드의 왼쪽 및 오른쪽 속성은 다음과 같습니다.

1. 왼쪽은 왼쪽 하위 트리 또는 해당 노드가 가리키는 선행 노드를 가리 킵니다. 예 : ① 왼쪽 노드가 가리키는 왼쪽 하위 트리, ⑩ 노드의 왼쪽이 선행 노드를 가리 킵니다.

2. 오른쪽은 오른쪽 하위 트리를 가리 키거나 후속 노드를 가리킬 수 있습니다. 예 : ① 오른쪽 노드는 오른쪽 하위 트리를 가리키고 ⑩ 노드의 오른쪽은 후속 노드를 가리 킵니다.

순차 스레딩 과정

1. 중간 순서 순회 순서에서 순회 할 첫 번째 노드는 8이고, 8 노드의 왼쪽 포인터는 null이므로 8 노드의 왼쪽 포인터는 이전 노드 인 null을 가리 킵니다.

이전 및 노드가 뒤로 이동

2. 중간 순서로 3 개 노드로 계속 트래버스하고 왼쪽 포인터가 null이 아닙니다.

pre는 8 개 노드이고 오른쪽 포인터는 비어 있으므로 오른쪽 포인터가 후속 노드 인 3을 가리 키도록합니다.

이전 및 노드가 뒤로 이동

3. 10 개의 노드로 계속 이동합니다. 왼쪽 포인터는 비어 있으므로 이전 노드를 가리 킵니다.

pre는 3 개의 노드이고 오른쪽 포인터가 비어 있지 않습니다.

이전 및 노드가 뒤로 이동

4. 노드 1로 계속 이동하고 왼쪽 포인터가 비어 있지 않습니다.

사전 노드는 10 개의 노드이고 오른쪽 포인터가 비어 있으므로 후속 노드 1을 가리 킵니다.

이전 및 노드가 뒤로 이동

5. 왼쪽 포인터가 비어 있지 않기 때문에 노드 14로 계속 이동하여 선행 노드 1을 가리 킵니다.

사전 노드는 1 노드이고 오른쪽 포인터가 비어 있지 않습니다.

이전 및 노드가 뒤로 이동

6. 6 개 노드로 계속 이동하고 왼쪽 포인터가 비어 있습니다.

오른쪽 포인터가 비어 있으므로 이전 노드는 14 개 노드이므로 후속 노드 6을 가리 킵니다.

이전 및 노드가 뒤로 이동

위는 순차 스레딩 노드의 프로세스입니다. 아래 코드 구현을 참조하십시오.

private void infixThreadedNode(HeroNode node) {
        if (node == null) {
            return;
        }
        //线索化左节点
        infixThreadedNode(node.getLeft());
        //线索化当前节点
        if (node.getLeft() == null) {
            node.setLeft(pre);
            node.setThreadedLeft(true);
        }
        if (pre != null && pre.getRight() == null) {
            pre.setRight(node);
            pre.setThreadedRight(true);
        }
        pre = node;
        //线索化右节点
        infixThreadedNode(node.getRight());
    }

순차 스레드 순회

public void infixThreadedList() {
        HeroNode node = root;
        while (node != null) {
            while (!node.isThreadedLeft()) {
                node = node.getLeft();
            }
            System.out.println(node);
            while (node.isThreadedRight()) {
                node = node.getRight();
                System.out.println(node);
            }
            node = node.getRight();
        }
    }

스레드 된 이진 트리 선주문

암호

 private void preThreadedNode(HeroNode node) {
        //线索化当前节点
        if (node == null)
            return;
        if (node.getLeft() == null) {
            node.setLeft(pre);
            node.setThreadedLeft(true);
        }
        if (pre != null && pre.getRight() == null) {
            pre.setRight(node);
            pre.setThreadedRight(true);
        }
        pre = node;
        //线索化左节点
        if (!node.isThreadedLeft()) {
            preThreadedNode(node.getLeft());
        }
        //线索化右节点
        if (!node.isThreadedRight()) {
            preThreadedNode(node.getRight());
        }
    }

사전 스레드 순회

public void preThreadedList() {
        HeroNode node = root;
        while (node != null) {
            if (!node.isThreadedLeft()) {
                System.out.println(node);
                node = node.getLeft();
            }
            System.out.println(node);
            node = node.getRight();
        }
    }

클라인 후 바이너리 트리

암호

private void postThreadedNode(HeroNode node) {
        if (node == null)
            return;
        postThreadedNode(node.getLeft());
        postThreadedNode(node.getRight());
        if (node.getLeft() == null) {
            node.setLeft(pre);
            node.setThreadedLeft(true);
        }
        if (pre != null && pre.getRight() == null) {
            pre.setRight(node);
            pre.setThreadedRight(true);
        }
        pre = node;
    }

클라인 후 순회

public void postThreadedList() {
        HeroNode node = root;
        while (node != null && !node.isThreadedLeft()) {
            node = node.getLeft();
        }
        pre = null;
        while (node != null) {
            if (node.isThreadedRight()) {
                System.out.println(node);
                pre = node;
                node = node.getRight();
            } else {
                if (node.getRight() == pre) {
                    System.out.println(node);
                    if (node == root)
                        return;
                    pre = node;
                    node = node.getParent();
                } else {
                    node = node.getRight();
                    while (node != null && !node.isThreadedLeft()) {
                        node = node.getLeft();
                    }
                }
            }
        }
    }

 

추천

출처blog.csdn.net/qq_45796208/article/details/111423923