앞 순서와 중간 순서로 두 갈래 트리 만들기
제목: 앞의 순서와 중간의 순서에 따라 대응하는 두 갈래 트리를 만듭니다.
순서: 16, 7, 6, 3, 14, 12, 8, 15, 28, 23, 27, 41, 30, 29, 55
및 중간 시퀀스: 3, 6, 7, 8, 12, 14, 15, 16, 23, 27, 28, 29, 30, 41, 55
검지offer 면접문제 6
사고방식: 1. 앞의 순서 반복 서열의 첫 번째 요소는 바로 루트 노드이다. 이것은 뒤의 순서 반복이 정돈된 것과 반대로 뒤의 순서 반복 서열은 마지막 요소는 루트 노드이다.
2. 전형적인 두 갈래 나무, 즉'왼쪽 노드는 아버지 노드보다 값이 작고 오른쪽 노드는 아버지 노드보다 값이 크다'는 두 갈래 나무는 중차 서열이 필요 없고 앞차나 뒤차로만 유일하게 두 갈래 나무를 확정할 수 있다.
3. 그러나 이런 문제에서 도출하고자 하는 두 갈래 나무는'왼쪽 노드는 아버지 노드보다 값이 작고 오른쪽 노드는 아버지 노드보다 값이 크다'는 규칙을 따르지 않아도 된다. 이때 단독의 앞 노드나 뒤 노드는 층별로 훑어보는 것을 포함하고 그 서열은 유일한 두 갈래 나무에 대응할 수 없다.반드시 중간 순서로 시퀀스를 옮겨야 한다.
원인은 매우 간단하다. 앞의 순서와 뒤의 순서가 왼쪽 작은 오른쪽의 큰 규칙을 따르지 않을 때 잎 노드가 아버지 노드의 왼쪽 아이인지 오른쪽 아이인지 확정할 수 없다.만약에 아버지 노드 A에 하위 노드 B가 있다면 왼쪽 아이가 B든 오른쪽 아이가 B든 전 서열 반복 결과는 영원히 AB이고 후 서열 반복 결과도 영원히 BA이다. 이때 전 서열 반복 서열과 후 서열 반복 서열을 동시에 정해도 도대체 B가 A의 왼쪽 노드인지 오른쪽 노드인지 알 수 없다.
그러나 앞서열이든 뒤서열이든 다시 중서열을 정한다면 B가 A의 왼쪽 노드든 오른쪽 노드든 정할 수 있다. 왜냐하면 중서 자체가 하위 노드가 아버지 노드의 왼쪽 아이든 오른쪽 아이든 정할 수 있기 때문이다.
4. 위의 1-3을 바탕으로 창설 방식은 다음과 같다. 1. 앞의 순서 반복 서열: 첫 번째는 루트 노드이고 중간 순서로 왼쪽 트리의 부분, 오른쪽 트리의 부분을 확정한다.
2. 왼쪽 나무의 첫 번째 노드, 왼쪽 나무의 뿌리 노드, 그리고 법대로 첫 번째 단계, 오른쪽 나무도 마찬가지로 이런 전형적인 사용은 귀속된다
중서의 좌우 경계 기능: 좌우 자목과 좌우 잎 노드를 효과적으로 구분하는 것이 이런 문제의 관건이다
3. 귀속 생성 노드, 귀속 종료 조건 즉 경계 조건 주의
후차 역행 서열 + 중차 역행 서열, 층차 역행 서열 + 중차 역행 서열은 모두 유사한 이치로 유일한 두 갈래 나무를 생성할 수 있다. 다른 것은 모두 안 된다. 왜냐하면 아이가 왼쪽인지 오른쪽인지 확인할 수 없기 때문이다.
코드:
#include
template struct Node {
T val;
Node *lchild;
Node *rchild;
Node(T _val):val(_val), lchild(nullptr), rchild(nullptr) {}
};
template class Btree {
Node *root;
public:
Btree():root(nullptr) {}
void Free (Node *cur) {
if (cur) {
Free(cur->lchild);
Free(cur->rchild);
delete cur;
cur = nullptr;
}
}
~Btree () {
Free(root);
}
void Add (T val) {
if (!root) {
root = new Node(val);
} else {
Node *cur = root;
while (cur) {
if (cur->val > val) {
if (cur->lchild) {
cur = cur->lchild;
} else {
cur->lchild = new Node(val);
break;
}
} else if (cur->val < val) {
if (cur->rchild) {
cur = cur->rchild;
} else {
cur->rchild = new Node(val);
break;
}
} else {
break;
}
}
}
}
void Pre (Node *cur) {
if (cur) {
std::cout << cur->val << "\t";
Pre(cur->lchild);
Pre(cur->rchild);
}
}
void pre () {
Pre(root);
std::cout << std::endl;
}
void Mid (Node *cur) {
if (cur) {
Mid(cur->lchild);
std::cout << cur->val << "\t";
Mid(cur->rchild);
}
}
void mid () {
Mid(root);
std::cout << std::endl;
}
};
void recreate (int *pre, int *mid, const int size, int prestart, int preend, int midstart, int midend, Btree &bt) {
if (preend - prestart != midend - midstart) {
return;
}
if (prestart > preend || midstart > midend || prestart >= size || preend >= size || !pre || !mid) {
return;
}
std::cout << "inesrt node idx " << prestart << "(" << pre[prestart] << ")" << std::endl;
bt.Add(pre[prestart]);
if (prestart == preend && midstart == midend) {
return;
}
int mididx = -1, count = 0;
for (int i = midstart; i <= midend; i++) {
if (pre[prestart] == mid[i]) {
mididx = i;
break;
} else {
++count;
}
}
std::cout << "left(pre; mid): " << (prestart + 1) << ", " << prestart + count << "; " << midstart << ", " << (mididx - 1) << std::endl;
std::cout << "right(pre; mid): " << (prestart + count + 1) << ", " << preend << "; " << (mididx + 1) << ", " << midend << std::endl << "---------------------" << std::endl;
if (mididx > 0) {
recreate(pre, mid, size, prestart + 1, prestart + count, midstart, mididx - 1, bt);
recreate(pre, mid, size, prestart + count + 1, preend, mididx + 1, midend, bt);
}
}
void recreate_btree_by_pre_and_mid (int *pre, int *mid, int size) {
Btree bt;
recreate(pre, mid, size, 0, size - 1, 0, size - 1, bt);
bt.pre();
bt.mid();
}
int main () {
int pre[] = {16, 7, 6, 3, 14, 12, 8, 15, 28, 23, 27, 41, 30, 29, 55};
int mid[] = {3, 6, 7, 8, 12, 14, 15, 16, 23, 27, 28, 29, 30, 41, 55};
recreate_btree_by_pre_and_mid(pre, mid, sizeof(pre)/sizeof(pre[0]));
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.