[cdev] Задача_6. гр 135

Алексей Петрунёв alexeypetrunev на gmail.com
Пт Апр 2 06:03:25 MSK 2010


Написал prioq_get, посмотрите.
----------- следущая часть -----------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


#define RIGHT_CHILD(i)  (((i) * 2) + 2)
#define PARENT(i)       (((i) - 1) / 2)
#define INIT_SIZE 2
#define GROW_SIZE	32
typedef int (*prioq_compare_t)(struct prioq_head *a, struct prioq_head *b);

struct prioq_head{
	    unsigned int index;
};		

struct user_data{
        struct prioq_head head;
		int data;
};		

struct prioq{
        struct prioq_head **heap;
	    size_t size;
        size_t used;
        prioq_compare_t compare;
};	


/*Создание очереди */
struct prioq *
prioq_new(prioq_compare_t compare)
{
	struct prioq *queue;

	queue = (struct prioq*)malloc(sizeof(struct prioq));

	if (queue == NULL) {
		fprintf(stderr, "prioq_new: can't allocate queue\n");
		return NULL;
	}

	memset(queue, 0, sizeof(*queue));

	queue->heap = (struct prioq_head**)malloc(sizeof(struct prioq_head *) * INIT_SIZE);

	if (queue->heap == NULL) {
		fprintf(stderr, "prioq_new: can't allocate heap\n");
		free(queue);
		return NULL;
	}

	memset(queue->heap, 0, sizeof(struct prioq_head *) * INIT_SIZE);

	queue->size = INIT_SIZE;
	queue->used = 0;
	queue->compare = ((compare != NULL) ? compare : compare);

	return queue;
}

#define NEW_SIZE(q)	(((q)->size + GROW_SIZE) * sizeof(struct prioq_head *))
#define OLD_SIZE(q)	((q)->size * sizeof(struct prioq_head *))

int prioq_put(struct prioq *queue, struct prioq_head *hp){

    int i;
	struct prioq_head** tmp;

	if (queue == NULL || hp == NULL) {
		fprintf(stderr, "prioq_put: NULL args\n");
		return NULL; 
    }
	if (queue->size == queue->used) {
		tmp = (struct prioq_head**)realloc(queue->heap, NEW_SIZE(queue));
		if (!tmp) {
			fprintf(stderr, "prioq_put: can't realloc heap\n");
			return -1;
		}
		queue->heap = tmp;
		memset(queue->heap + OLD_SIZE(queue), 0,
		       NEW_SIZE(queue) - OLD_SIZE(queue));
		queue->size += GROW_SIZE;
		
	}

	i = queue->used++;

	while (i && queue->compare(queue->heap[PARENT(i)], hp) < 0) {
 		queue->heap[i] = queue->heap[PARENT(i)];
		queue->heap[i]->index = i;
		i = PARENT(i);
	}

	queue->heap[i] = hp;
	hp->index = i;
    
	return 0;

}	

/*Функция сравнения*/
int
compare(struct prioq_head *a, struct prioq_head *b)
{
	struct user_data *ap = (struct user_data *) a;
	struct user_data *bp = (struct user_data *) b;

	if (ap->data > bp->data)
		return 1;
	else if (ap->data < bp->data)
		return -1;
	return 0;
}

/*---------------------------------------------*/
#define LEFT_CHILD(i)   (((i) * 2) + 1) 
int
prioq_heapify(struct prioq *queue)
{
    unsigned int index, largest;	
	
	struct prioq_head* tmp;
	
	for (index = 0,largest = LEFT_CHILD(index);
	    largest < queue->used;
        index = largest, largest = LEFT_CHILD(index)) {
		
        if (queue->compare(queue->heap[largest],
			queue->heap[largest+1]) < 0) {
            
			largest++;			
        }
	    if (queue->
			compare(queue->heap[index],
			queue->heap[largest])<0) {
			
			tmp = queue->heap[largest];
			queue->heap[largest] = queue->heap[index];
			queue->heap[largest]->index = index;
			queue->heap[index] = tmp;
			queue->heap[index]->index = largest;
		}
		else return 0;
	}	
	if ((largest == queue->used) 
		&& (queue->compare(queue->heap[index],
		    queue->heap[largest]) < 0)) {
        
		tmp = queue->heap[largest];
		queue->heap[largest] = queue->heap[index];
		queue->heap[largest]->index = index;
		queue->heap[index] = tmp;
		queue->heap[index]->index = largest;
	}
	
	return 1;	
}


/*------------------------------------------------*/
void 
prioq_remove(struct prioq *queue, struct prioq_head *hp) 
{
    
	if (hp->index > queue->used)
        fprintf(stderr,"prioq_remove: index out of range\n");
	
	int index = hp->index;
	
	while (index > 0){
	    queue->heap[index] = queue->heap[PARENT(index)];
		queue->heap[index]->index = PARENT(index); 
        index = PARENT(index);
	}
	
	queue->used--;
	
	int used = queue->used;
	queue->heap[0] = queue->heap[used];
    queue->heap[0]->index = used;
	prioq_heapify(queue);
}	

void
prioq_free(struct prioq* queue)
{
    if (queue == NULL) {
        fprintf(stderr,	"prioq_free:The queue not exists\n");
	}	
	else {
	    free(queue->heap);
		free(queue);
		fprintf(stderr,"prioq_free: the queue is free\n");	
	}
	
}	

struct prioq_head *
prioq_peek(struct prioq*queue) 
{
    struct user_data* ptr;
	struct prioq_head* head = queue->heap[0];
	if (queue == NULL) {
		fprintf(stderr,
		"prioq_peek: Can't peek head from queue\n");
		return NULL;
	}
 	if (queue != NULL) {
	    
		if (queue->heap == NULL) {
			fprintf(stderr,
		    "prioq_peek: Can't peek head from queue\n");
		    return NULL;
		} 
		if ((queue->heap != NULL) 
			 && (head != NULL)) {
			ptr = (struct user_data*)head;
	        fprintf(stderr,"prioq_peek:head of queue\n data:%i\n index:%d\n",ptr->data,0);
		}
		else {
            fprintf(stderr,
		    "prioq_peek: Can't peek head from queue\n");
		    return NULL;
 		}	
	}
	return head;
}

struct prioq_head *
prioq_get(struct prioq*queue)
{
	struct prioq_head* head = queue->heap[0];
	struct user_data* ptr;
	unsigned int used;
	
	if (queue == NULL) {
		fprintf(stderr,
		"prioq_get: Can't extract head from queue \n");
		return NULL;
	}
	if ((queue != NULL) && (head != NULL)) {
		ptr = (struct user_data*)head;
		fprintf(stderr,
		"prioq_get: the head of queue\n %d-data\n %d-index",
		ptr->data,0);
		
		used = queue->used;
		if (used > 1) {
		    queue->heap[0] = queue->heap[used];
		    queue->heap[0]->index = used;
		    queue->used--;
		    free(queue->heap[used]);
		    prioq_heapify(queue);
	    } 
		else if (used == 1) {
				free(queue->heap[0]);
				queue->used--;
		}
        else return NULL; 		
	}	
	return head;	
}	
	
int main(void){
    struct prioq *q=prioq_new(compare); 
    struct user_data a,b;
	struct prioq_head *p,*s;
	//struct user_data* dat;
		
    a.data = 0;
    b.data = 5;
	p = &a.head;
	s = &b.head;
		
	prioq_put(q,p);
	prioq_put(q,s);
	prioq_peek(q);
	prioq_get(q);
	
	return q->used;	
}
  	



Подробная информация о списке рассылки cdev