Итак, вопрос очень похож на ребус. Но прежде всего нам нужно понять нашу проблему и какую информацию мы можем из нее извлечь.

Позвольте мне привести вам простой пример,

Предзаказ[] = {1, 2, 4, 5, 3, 6, 7}

PostOrder[] = {4, 5, 2, 6, 7, 3, 1}

Здесь корень прямо сейчас равен 1, потому что он должен был выполнить предварительный заказ при создании обхода PreOrder по его определению. Кроме того, он будет последним в обходе PostOrder.

Затем вы можете заметить, что человек справа от 1 является его левым дочерним элементом в предварительном порядке, т. е. 2. Точно так же 3 должен быть правым дочерним элементом 1, называемым сейчас Root.

Таким образом, мы можем легко найти корень, левый дочерний элемент и правый дочерний элемент сразу из заданной последовательности. Следующее, что мы хотим увидеть, это левый дочерний элемент в PostOrder и правый дочерний элемент в PreOrder. Тогда мы получим обходы секционированного порядка примерно так:

Предзаказ[] = {1, |2, 4, 5,| 3, 6, 7}

PostOrder[] = {4, 5, 2,| 6, 7, 3,| 1}

Отсюда мы получаем мотивацию для чего-то вроде рекурсии. Итак, теперь нам нужно написать функцию, которая поможет нам в распространении этой рекурсии. Теперь нам нужно решить, какие параметры должна принимать наша функция для распространения этой рекурсии. Ему нужны оба секционированных массива обходов, вот и все. Это все, что нам нужно. Поскольку C не позволяет нам нарезать массивы, мы будем работать с индексами. Это хорошо.

Но если мы продолжаем рекурсию, нам нужно подумать и о завершении. Вот возможные случаи прекращения, о которых мы можем подумать.

Завершение 1 (когда в массиве остается 1 элемент): Итак, если ваша программа работала правильно, то все готово, но рекурсивный характер убьет все. Итак, это условие наступит, когда останется только один элемент. Затем мы создадим узел, но он левый дочерний, а правый дочерний нужно установить равным нулю, и наша программа завершится.

Завершение 2 (когда в массиве остаются два элемента): поскольку мы кодируем Двоичное дерево поиска, мы можем предположить, что левый дочерний элемент всегда будет первым. И здесь наша программа также обрывается.

Ниже приведена полная программа и работающая демонстрация, но я настоятельно рекомендую вам зайти сюда только после того, как вы потратите на это почти неделю, в противном случае идите и поищите что-нибудь еще для оттачивания своих навыков.

typedef struct Tree_Node
{
 int data;
 struct Tree_Node* Left_Child;
 struct Tree_Node* Right_Child;
}Tree_Node;
void Make(Tree_Node **imp, int *PreO, int *PostO, int pr_st, int pr_fin, int pt_st, int pt_fin)
{
 printf(“Call no %d\n”, i++);
 if( pr_st==pr_fin ) //Termination Case 1 when single element remains
 {
 Tree_Node*t;
 t = (Tree_Node*)malloc(sizeof(Tree_Node));
 t->data = PreO[pr_st];
 t->Left_Child = t->Right_Child = NULL;
 *imp = t; //Actual Linking
 return;
 }
 else if( pr_st+2 == pr_fin ) //Termination Case 2 when three element remains
 {
 Tree_Node *t, *tlc, *trc;
 t = (Tree_Node*)malloc(sizeof(Tree_Node));
 tlc = (Tree_Node*)malloc(sizeof(Tree_Node));
 trc = (Tree_Node*)malloc(sizeof(Tree_Node));
 t->data = PreO[pr_st];
tlc->data = PreO[pr_st+1];
 trc->data = PreO[pr_st+2];
tlc->Right_Child = tlc->Left_Child = NULL;
 trc->Right_Child = trc->Left_Child = NULL;
t->Left_Child = tlc;
 t->Right_Child = trc;
 (*imp) = t; //Actual Linking
 return;
 }
 else if( pr_st+1 == pr_fin ) //Termination Case 3 when two element remains,
 {
 Tree_Node*t, *t1;
 t = (Tree_Node*)malloc(sizeof(Tree_Node));
 t1 = (Tree_Node*)malloc(sizeof(Tree_Node));
t->Right_Child = t->Left_Child = NULL;
 t1->Right_Child = t1->Left_Child = NULL;
t->data = PreO[pr_st];
 t1->data = PreO[pr_fin];
 t->Left_Child = t1;
(*imp) = t; //Actual Linking
 return;
 }
 else //No termination, further Propagation
 {
 Tree_Node*t;
 t = (Tree_Node*)malloc(sizeof(Tree_Node));
 t->data = PreO[pr_st];
 t->Left_Child = t->Right_Child = NULL;
 (*imp) = t; //Actual Linking
int lc_p = Give_Me_Index( PreO[pr_st+1], PostO); //finding the position of left child in PostOrder
 int rc_p = Give_Me_Index( PostO[pt_fin-1], PreO); //finding the position of right child in PreOrder
Make(&t->Left_Child, PreO, PostO, pr_st+1, rc_p-1, pt_st, lc_p);
 Make(&t->Right_Child, PreO, PostO, rc_p, pr_fin, lc_p+1, pt_fin-1);
 return;
 }
}
int Give_Me_Index(int num, int A[])
{
 int p = 0;
 while( A[p]!=num ){ p++; } //go ahead until you find it
 return p;
}
void Inorder(Tree_Node* x)
{
 if(x)
 {
 if(x->Left_Child) Inorder(x->Left_Child);
 printf(“..%d..\n”, x->data); //data in the middle
 if(x->Right_Child) Inorder(x->Right_Child);
 }
}
int main()
{
 int n = 11;
 Tree_Node* Root;
int PreO[] = {1, 2, 4, 3, 5, 6, 13, 8, 7, 11, 12};
 int PostO[] = {2, 5, 13, 8, 6, 3, 11, 12, 7, 4, 1};
Make(&Root, &PreO, &PostO, 0, n-1, 0, n-1);
 Inorder(Root);
 Delete(Root);
 return 0;
}

Ниже приведена демонстрация описанной выше программы.

Спасибо, что прочитали эту статью, и я надеюсь, что она поможет вам, иначе Google и Youtube всегда будут рядом.

Приятного обучения (: — — — :)

/* Пишите мне по любым вопросам [email protected] */