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;
}

Программа работает корректно.Не кидайтесь тапками, заранее спасибо за помощь.


Ответы (0 шт):