나는 내 인생에서 BST를 많이 사용했지만 Inorder traversal 이외의 것을 사용하는 것을 고려한 적이 없다는 것을 최근 깨달았습니다.
이것을 깨달은 후, 나는 나의 오래된 데이터 구조 교과서를 뽑아 내고 선주문과 주문 후 순회의 유용성 뒤에있는 추론을 찾았습니다. 그들은 많이 말하지 않았습니다.
사전 주문 / 후 주문을 실제로 사용하는 경우의 몇 가지 예는 무엇입니까? 순서대로하는 것보다 언제 더 의미가 있습니까?
나는 내 인생에서 BST를 많이 사용했지만 Inorder traversal 이외의 것을 사용하는 것을 고려한 적이 없다는 것을 최근 깨달았습니다.
이것을 깨달은 후, 나는 나의 오래된 데이터 구조 교과서를 뽑아 내고 선주문과 주문 후 순회의 유용성 뒤에있는 추론을 찾았습니다. 그들은 많이 말하지 않았습니다.
사전 주문 / 후 주문을 실제로 사용하는 경우의 몇 가지 예는 무엇입니까? 순서대로하는 것보다 언제 더 의미가 있습니까?
답변:
바이너리 트리에 대해 사전 주문, 순서 및 사후 주문을 사용하는 상황을 이해하기 전에 각 순회 전략이 어떻게 작동하는지 정확히 이해해야합니다. 다음 트리를 예로 사용하십시오.
트리의 루트는 7 , 가장 왼쪽 노드는 0 , 가장 오른쪽 노드는 10 입니다.
선주문 순회 :
요약 : 루트 ( 7 ) 에서 시작하여 맨 오른쪽 노드 ( 10 ) 에서 끝납니다.
순회 시퀀스 : 7, 1, 0, 3, 2, 5, 4, 6, 9, 8, 10
순회 순회 :
요약 : 맨 왼쪽 노드 ( 0 )에서 시작하여 맨 오른쪽 노드 ( 10 ) 에서 끝납니다.
순회 시퀀스 : 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
주문 후 순회 :
요약 : 가장 왼쪽 노드 ( 0 )에서 시작하여 루트 ( 7 )로 끝납니다.
순회 시퀀스 : 0, 2, 4, 6, 5, 3, 1, 8, 10, 9, 7
프로그래머가 선택하는 순회 전략은 설계중인 알고리즘의 특정 요구 사항에 따라 다릅니다. 목표는 속도이므로 가장 빠르게 필요한 노드를 제공하는 전략을 선택하십시오.
잎을 검사하기 전에 뿌리를 조사해야한다는 것을 알고 있다면 모든 잎 보다 먼저 모든 뿌리를 만나게되므로 사전 주문 을 선택 하십시오.
노드보다 먼저 모든 잎을 탐색해야한다는 것을 알고 있다면 잎 을 찾기 위해 뿌리를 검사하는 데 시간을 낭비하지 않기 때문에 주문 후 를 선택 합니다.
당신이 트리 노드에 고유의 순서를 가지고 있음을 알고, 당신은보다 더 원래의 순서로 트리 다시 평평 할 경우 에 차 통과를 사용해야합니다. 나무는 만들어진 것과 같은 방식으로 평평 해집니다. 사전 주문 또는 사후 주문 순회는 트리를 생성하는 데 사용 된 시퀀스로 다시 풀리지 않을 수 있습니다.
struct Node{
int data;
Node *left, *right;
};
void preOrderPrint(Node *root)
{
print(root->name); //record root
if (root->left != NULL) preOrderPrint(root->left); //traverse left if exists
if (root->right != NULL) preOrderPrint(root->right);//traverse right if exists
}
void inOrderPrint(Node *root)
{
if (root.left != NULL) inOrderPrint(root->left); //traverse left if exists
print(root->name); //record root
if (root.right != NULL) inOrderPrint(root->right); //traverse right if exists
}
void postOrderPrint(Node *root)
{
if (root->left != NULL) postOrderPrint(root->left); //traverse left if exists
if (root->right != NULL) postOrderPrint(root->right);//traverse right if exists
print(root->name); //record root
}
선주문 : 나무의 사본을 만드는 데 사용됩니다. 예를 들어, 트리의 복제본을 생성하려면 사전 주문 순회를 통해 노드를 어레이에 배치합니다. 그런 다음 배열의 각 값에 대해 새 트리에서 삽입 작업을 수행합니다 . 원래 트리의 사본이 생성됩니다.
In-order : : BST에서 비 감소 순서로 노드 값을 가져 오는 데 사용됩니다.
주문 후 : : 잎에서 뿌리까지 나무를 삭제하는 데 사용됩니다.
사전 및 사후 주문은 각각 하향식 및 상향식 재귀 알고리즘과 관련됩니다. 반복적 인 방식으로 이진 트리에 주어진 재귀 알고리즘을 작성하려는 경우 이것이 기본적으로 수행 할 작업입니다.
또한 사전 및 사후 주문 시퀀스가 함께 트리를 완전히 지정하여 간결한 인코딩을 생성합니다 (최소한 희소 트리의 경우).
이 차이가 실제 역할을하는 것을 볼 수있는 곳이 많습니다.
제가 지적 할 하나의 훌륭한 점은 컴파일러를위한 코드 생성입니다. 다음 진술을 고려하십시오.
x := y + 32
이를위한 코드를 생성하는 방법은 (물론 순진하게) 먼저 y를 레지스터에로드하고 32를 레지스터에로드 한 다음 두 개를 추가하는 명령어를 생성하는 코드를 생성하는 것입니다. 조작하기 전에 무언가가 레지스터에 있어야하기 때문에 (상수 피연산자를 항상 수행 할 수 있지만 무엇이든 할 수 있다고 가정합시다) 이런 방식으로 수행해야합니다.
일반적으로이 질문에 대해 얻을 수있는 답변은 기본적으로 다음과 같이 축소됩니다. 데이터 구조의 다른 부분을 처리하는 사이에 약간의 의존성이있을 때 차이가 실제로 중요합니다. 요소를 인쇄 할 때, 코드를 생성 할 때 (외부 상태가 차이를 만들 때, 물론 모나드 방식으로도 볼 수 있음) 또는 먼저 처리되는 자식에 따라 계산을 포함하는 구조에 대해 다른 유형의 계산을 수행 할 때 이것을 볼 수 있습니다. .