C/C++ Обход бинарного дерева в ширину
Я новичок, но я бы очень хотел разобраться, как это работает, поэтому буду весьма признателен, если Вы мне подскажите те моменты, которые я не понимаю.. (Да, мне необходимо разобраться в чужом коде, но я действительно хочу понять, что к чему.)
typedef struct node {
const void* ptr;
struct node* next;
} node_t;
typedef struct {
node_t* head;
node_t* tail;
} queue_t;
typedef struct tree {
int key;
struct tree* left;
struct tree* right;
} tree_t;
1-е узел очереди (для чего нужен const void* ptr;?Почему именно const void*..), 2-е очередь для обхода дерева в ширину, 3-е -двоичное дерево поиска.
void queue_init(queue_t* q){ q->head = q->tail = NULL; }
int queue_empty(queue_t* q) { return (q->head == NULL); }
Что значит вот эта функция?Вроде с предыдущими двумя более менее понятно..Одна из них инициализирует очередь, другая - проверка на пустую очередь..Но эта?..
const void* queue_front(queue_t* q) { return q->head->ptr; }
Далее..добавление в очередь.Тут я конкретно запутался (queue_t* q и node_t* p - что значат буквы q и p после указателей, связанных с вышеописанными структурами?)Да еще и поиттер (ptr ) ..как это работает? :(
int queue_push(queue_t* q, const void* ptr){
node_t* p = (node_t*)malloc(sizeof(node_t));
if(p != NULL){
p->ptr = ptr;
p->next = NULL;
if(q->head == NULL)
q->head = q->tail = p;
else {
q->tail->next = p;
q->tail = p;
}
}
return (p != NULL);
}
Удаление из очереди.Тут вроде всё понятно для меня.
void queue_pop(queue_t* q){
node_t* t;
if(q->head != NULL){
t = q->head;
q->head = q->head->next;
free(t);
if(q->head == NULL)
q->tail = NULL;
}
}
Самая важная часть программы.Функция обхода дерева в ширину.Я к сожалению, не совсем понимаю, как должен работать данный алгоритм, даже смотря на функции, поэтому, если вы можете объяснить, как он осуществляется, было бы здорово..Т.е. сам принцип.
void tree_out_width(FILE* _out, const tree_t* tr){
const tree_t* p;
queue_t q;
queue_init(&q);
queue_push(&q, tr);
while(! queue_empty(&q)){
p = (const tree_t*)queue_front(&q);
queue_pop(&q);
fprintf(_out, "%d ",p->key);
if(p->left != NULL)
queue_push(&q, p->left);
if(p->right != NULL)
queue_push(&q, p->right);
}
}
Я не совсем понял, почему моя закоменченная реализация оказалось не правильной, был бы рад объяснению.
tree_t* tree_insert(tree_t** tr, int key){
/* if (*tr == NULL){
*tr = (tree_t*)malloc(sizeof(tree_t));
*tr->p=key;
*tr->left=NULL;
*tr->right=NULL;
return p;
}
else{
if(key>=*tr->p){
tree_insert(*tr->right,key);
}
else tree_insert(*tr->left,key);
}
}*/
tree_t* p = *tr;
while(p != NULL){
if(key < p->key){
tr = &p->left;
p = p->left;
}
else {
tr = &p->right;
p = p->right;
}
}
p = (tree_t*)malloc(sizeof(tree_t));
if(p != NULL){
p->key = key;
p->left = p->right = NULL;
*tr = p;
}
return p;
}
С функцией очистки дерева вопросов нет.
void tree_clear(tree_t* tr){
if(tr != NULL){
if(tr->left != NULL)
tree_clear(tr->left);
if(tr->right != NULL)
tree_clear(tr->right);
free(tr);
}
}
И сам мэйн.
int main(){
tree_t* tr = NULL;
int n , fir, el, t, i;
printf ("enter number of elements in the tree :");
scanf ("%d",&n);
printf ("enter the root :");
scanf ("%d",&fir);
tr = tree_insert(&tr, fir);
for (i=1; i<n;i++){
scanf ("%d",&el);
t = el;
tree_insert(&tr, t);
}
printf ("\n");
tree_out_width(stdout, tr);
tree_clear(tr);
return 0;
}
Программа работает корректно.Не кидайтесь тапками, заранее спасибо за помощь.