二项队列实现文件C语言

/*	binomial-queue.c --  二项队列实现文件	*/
#include "binomial-queue.h"

/*	局部函数声明	*/

static SubTree Combine_Trees (SubTree t1, SubTree t2) ;
static Node * Make_Node (const Item item) ;
static void Recursively (const SubTree t, void (* pfun) (const Item item)) ;

/*	接口函数定义	*/

int InitializeBinQueue (BinQueue * const pbq, const int size)
{
	int i ;

	if (size <= 0)
		return 0 ;
	*pbq = (struct binqueue *) malloc (sizeof (struct binqueue)) ;
	if (NULL == *pbq)
		return 0 ;
	(*pbq) -> forest = (SubTree *) malloc (sizeof (SubTree) * size) ;
	if (NULL == (*pbq) -> forest)
	{
		free (*pbq) ;
		return 0 ;
	}
	for (i = 0; i < size; i++)
		(*pbq) -> forest[i] = NULL ;
	(*pbq) -> size = size ;
	(*pbq) -> current = 0 ;

	return 1 ;
}

int BinQueueIsEmpty (const BinQueue bq)
{
	return 0 == bq -> current ;
}

BinQueue Merge (BinQueue bq1, BinQueue bq2)
{
	BinQueue temp ;
	SubTree t1, t2, carry = NULL ;
	int i, j, ct, index = 0 ;

	//	此处的检测, 很重要.
	if (bq1 == bq2)
		return bq1 ;
	if (bq1 -> current + bq2 -> current > bq1 -> size)
		return bq1 ;
	bq1 -> current += bq2 -> current ;
	//	保障 bq1 -> current > bq2 -> current								-->
	if (bq1 -> current < bq2 -> current)
	{
		temp = bq1 ;
		bq1 = bq2 ;
		bq2 = temp ;
	}
	//	这样就可以通过下面的 bq2 所有子树都已被合并过的条件检测有
	//	效地避免当 bq2 -> current 很小的时候将造成的太多次不必要的条件检测	-->
	for (i = 0, j = 1, ct = 0; j <= bq1 -> current; i++, j *= 2)
	{
		t1 = bq1 -> forest[i] ;
		//	以下判断是为了应对Insert的情况, 因为我在Insert时只分配了1棵子树的空间
		if (1 == index)
			t2 = NULL ;
		else if (1 == bq2 -> size)
		{
			index = 1 ;
			t2 = bq2 -> forest[i] ;
		}
		else
			t2 = bq2 -> forest[i] ;
		//	这个方法真的很巧妙, 开了眼界
		switch (!!t1 + 2 * !!t2 + 4 * !!carry)
		{
			//	no trees
			case 0 :	break ;
			//	only bq1
			case 1 :	if (ct == bq2 -> size)
						{
							Release (bq2) ;
							return bq1 ;
						}
						break ;
			//	only bq2
			case 2 :	bq1 -> forest[i] = t2 ;
						bq2 -> forest[i] = NULL ;
						ct++ ;
						break ;
			//	only carry
			case 4 :	bq1 -> forest[i] = carry ;
						carry = NULL ;
						break ;
			//	bq1 and bq2
			case 3 :	carry = Combine_Trees (t1, t2) ;
						bq1 -> forest[i] = bq2 -> forest[i] = NULL ;
						ct++ ;
						break ;
			//	bq1 and carry
			case 5 :	carry = Combine_Trees (t1, carry) ;
						bq1 -> forest[i] = NULL ;
						break ;
			//	bq2 and carry
			case 6 :	carry = Combine_Trees (t2, carry) ;
						bq2 -> forest[i] = NULL ;
						ct++ ;
						break ;
			//	all there
			case 7 :	bq1 -> forest[i] = carry ;
						carry = Combine_Trees (t1, t2) ;
						bq2 -> forest[i] = NULL ;
						break ;
		}
	}

	return bq1 ;
}

BinQueue Insert (BinQueue bq, const Item item)
{
	BinQueue temp ;
	int size = 1 ;

	if (bq -> size == bq -> current)
		return bq ;
	if (!InitializeBinQueue (&temp, size))
	{
		free (temp -> forest) ;
		free (temp) ;
		return bq ;
	}
	temp -> forest[0] = Make_Node (item) ;
	if (NULL == temp -> forest[0])	// 话说这个位置原先有一个";"
	{
		free (temp -> forest[0]) ;
		free (temp) ;
		return bq ;
	}
 	temp -> current = 1 ;
	bq = Merge (bq, temp) ;

	return bq ;
}

Item DeleteMin (BinQueue bq)
{
	BinQueue deleted_queue ;
	SubTree deleted_tree, old_root ;
	Item min ;
	int i, j, size, min_index ;

	if (BinQueueIsEmpty (bq))
		return -INFINITY ;
	min = INFINITY ;
	for (i = 0, size = bq -> size; i < size; i++)
	{
		if (bq -> forest[i] && bq -> forest[i] -> item < min)
		{
			min = bq -> forest[i] -> item ;
			min_index = i ;
		}
	}
	if (INFINITY == min)
		return INFINITY ;
	deleted_tree = bq -> forest[min_index] ;
	old_root = deleted_tree ;
	deleted_tree = deleted_tree -> left ;
	free (old_root) ;
	InitializeBinQueue (&deleted_queue, (1 << min_index) - 1) ;
	for (j = min_index - 1; j >= 0; j--)
	{
		deleted_queue -> forest[j] = deleted_tree ;
		deleted_tree = deleted_tree -> nextsibling ;
		deleted_queue -> forest[j] -> nextsibling = NULL ;
	}
	bq -> forest[min_index] = NULL ;
	bq -> current -= deleted_queue -> current + 1 ;

	bq = Merge (bq, deleted_queue) ;

	return min ;
}

void Traversal (const BinQueue bq, void (* pfun) (const Item item))
{
	int i, size ;

	for (i = 0, size = bq -> size; i < size; i++)
		if (bq -> forest[i])
			Recursively (bq -> forest[i], pfun) ;
}

void Release (const BinQueue bq)
{
	int i, size ;

	for (i = 0, size = bq -> size; i < size; i++)
	{
		if (bq -> forest[i])
			free (bq -> forest[i]) ;
	}
	free (bq) ;
}

/*	局部函数定义	*/

static SubTree Combine_Trees (SubTree t1, SubTree t2)
{
	if (t1 -> item > t2 -> item)
		return Combine_Trees (t2, t1) ;	//	话说这个地方的 t1 原来是 t2, 真不知道我这一天都在想些什么
	t2 -> nextsibling = t1 -> left ;
	t1 -> left = t2 ;

	return t1 ;
}

static Node * Make_Node (const Item item)
{
	Node * new_node ;

	new_node = (Node *) malloc (sizeof (Node)) ;
	if (NULL == new_node)
		return NULL ;
	new_node -> item = item ;
	new_node -> left = new_node -> nextsibling = NULL ;

	return new_node ;
}

static void Recursively (const SubTree t, void (* pfun) (const Item item))
{
	if (t -> left)
		Recursively (t -> left, pfun) ;
	if (t -> nextsibling)
		Recursively (t -> nextsibling, pfun) ;
	(* pfun) (t -> item) ;
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现队列存入文件,可以考虑以下几个步骤: 1. 定义队列结构体,包括队列的头节点、尾节点、节点数量和节点数据类型等信息。 ``` typedef struct node { int data; struct node* next; } Node; typedef struct queue { Node* head; Node* tail; int size; } Queue; ``` 2. 初始化队列,将头节点和尾节点都指向NULL,节点数量设为0。 ``` void initQueue(Queue* q) { q->head = NULL; q->tail = NULL; q->size = 0; } ``` 3. 实现入队操作,将新节点加入队列末尾,同时更新尾节点和节点数量。 ``` void enqueue(Queue* q, int data) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = data; newNode->next = NULL; if (q->head == NULL) { q->head = newNode; } else { q->tail->next = newNode; } q->tail = newNode; q->size++; } ``` 4. 实现出队操作,将队列头节点弹出,同时更新头节点和节点数量。 ``` int dequeue(Queue* q) { if (q->head == NULL) { return -1; // 队列为空,返回错误码 } int data = q->head->data; Node* temp = q->head; q->head = q->head->next; free(temp); q->size--; return data; } ``` 5. 将队列中的数据存入文件,可以使用标准C库中的文件操作函数,例如fopen、fprintf和fclose等。 ``` void saveQueue(Queue* q, char* filename) { FILE* fp = fopen(filename, "w"); if (fp == NULL) { printf("Error opening file.\n"); return; } Node* curr = q->head; while (curr != NULL) { fprintf(fp, "%d\n", curr->data); curr = curr->next; } fclose(fp); } ``` 完整代码示例: ``` #include <stdio.h> #include <stdlib.h> typedef struct node { int data; struct node* next; } Node; typedef struct queue { Node* head; Node* tail; int size; } Queue; void initQueue(Queue* q) { q->head = NULL; q->tail = NULL; q->size = 0; } void enqueue(Queue* q, int data) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = data; newNode->next = NULL; if (q->head == NULL) { q->head = newNode; } else { q->tail->next = newNode; } q->tail = newNode; q->size++; } int dequeue(Queue* q) { if (q->head == NULL) { return -1; } int data = q->head->data; Node* temp = q->head; q->head = q->head->next; free(temp); q->size--; return data; } void saveQueue(Queue* q, char* filename) { FILE* fp = fopen(filename, "w"); if (fp == NULL) { printf("Error opening file.\n"); return; } Node* curr = q->head; while (curr != NULL) { fprintf(fp, "%d\n", curr->data); curr = curr->next; } fclose(fp); } int main() { Queue q; initQueue(&q); enqueue(&q, 1); enqueue(&q, 2); enqueue(&q, 3); saveQueue(&q, "queue.txt"); return 0; } ``` 运行此程序后,会在当前目录下生成一个名为“queue.txt”的文件,其中包含队列中的所有元素(每个元素占一行)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值