c语言(队列代码分析)

队列是在链表的基础上,进行一种规范(增删的顺序)和属性的增加(增加了项数)
这里的例子是"顾客咨询排队问题"

一.数据的构建

1.项的构建---------只包含基础数据类型,并用结构体打包

typedef struct item
{
	long arrive;//一位顾客加入队列的时间
	int  processtime;//该顾客咨询话费的时间
}Item;

2.节点的构建------项加上指向其他节点的指针

typedef struct node//创建链表-------------------------------节点
{
	Item item;
	struct node *next;
}Node;

3.队列的构建(相对于链表的新增)-------2个指针(用来表明的前指针和用来标明队列的尾指针)和项数

typedef struct queue//建立队列---节点排列的一种方式----------队列
{
	Node * front;
	Node * rear;
	int items;
}Queue;

二.队列的一些申明

- 第一部分-----初始化以及一些检查函数

/*初始化*/
void InitializeQueue(Queue * pq)
{
	//头指针
	pq->front = NULL;
	//尾指针
	pq->rear = NULL;
	//项数
	pq->items = 0;
}

/*判断----空*/
bool QueueIsEmpty(const Queue* pq)
{
	//如果项数是0  就返回true
	return pq->items == 0;
}

/*判断---满*/
bool QueueIsFull(const Queue* pq)
{
	//如果项数是满的  就返回true
	return pq->items == MAXQUEUE;
}

/*查---项数*/
int QueueItemCount(const Queue* pq)
{
	//返回队列中的项数
	return pq->items;
}

说明:
(1)初始化:队列的初始化,让2个指针指向null,项数为0
(2)判断是否为空,是否为满:通过判断项数的情况进行判断
(3)查项数:返回项数的值即可

- 第二部分-----队列的一些操作

/*增---添加项数*/
bool EnQueue(Item item, Queue*pq)
{
	/*添加项数只能从队列后面的添加*/
	
	//创建一个节点
	Node * pnew;
	//---检测是否创建成功---1.看队列是否满了 2.看分配空间是否成功
	if (QueueIsFull(pq))
		return false;

	pnew = (Node*)malloc(sizeof(Node));
	if (pnew == NULL)
	{
		fprintf(stderr, "为节点分配空间出现问题\n");
		exit(EXIT_FAILURE);
	}

	//初始化节点----项,指针
	CopyToNode(item, pnew);
	pnew->next = NULL;
	//判断节点是否为第一个节点
	if (QueueIsEmpty(pq))
		pq->front = pnew;
	//---不是的话  节点的拼接操作----尾端的下一个指针 指向新节点
	else
	{
		pq->rear->next = pnew;
	}
	//更新尾部指针
	pq->rear = pnew;
	//项数加1
	pq->items++;

	return true;

}

/*删---删除项数*/
bool DeQueue(Item *pitem, Queue* pq)
{
	/*删除项数只能从队列前面删*/

	//创建一个节点(替死鬼)指针
	Node * pt;
	//判断队列是否为空--为空的话 就执行不了删除操作
	if (QueueIsEmpty(pq))
		return false;
	//调用函数  取出非指针部分(项)---这样的删除是可以恢复的(数据没丢)??
	CopyToItem(pq->front, pitem);
	//新节点指针指向要被删除的节点(首节点)
	pt = pq->front;
	//让队列首指针指向下一个节点
	pq->front = pq->front->next;
	//释放替死鬼指针里的内容
	free(pt);
	//队列项目数减1
	pq->items--;
	//判断队列里的项目数是否为0---如果为0  就不存在尾指针
	if (pq->items == 0)
	{
		pq->rear = NULL;
	}
	return true;
}

/*清空*/
void EmptyTheQueue(Queue* pq)
{
	/*相当于清空了所有的节点*/
	//创建一个项 作为垃圾站(存放要被删除的项)
	Item dummy;
	//如果队列不是空的--就一直删除节点
	while (!QueueIsEmpty(pq))
	{
		DeQueue(&dummy, pq);
	}
}

说明:

- (1)增添项数的操作:通过创建节点,把节点加入到队列中实现

其中节点的初始化用到了辅助函数

static void CopyToNode(Item item, Node* pn)
{
	pn->item = item;
}


辅助函数是把项中的内容(item)送到节点中项的部分(pn->item = item;)
这个函数的操作流程是:
1.创建一个指向节点结构的指针(pnode)------作用类似于"current"指针
2.对队列情况的判断-------满了就不能添加了
3.对此指针指向节点的初始化(先请求分配空间,分配空间同意后,项(辅助函数)和指针(指向下一节点)的初始化)
4.对队列情况的判断------如果(1)队列是空的,这个新节点就是"头部了"(用前指针指向这个节点)
(2)队列不是空的:那就让队列"屁股节点"(pq->rear)的"小尾巴"(pq->rear->next)指向这个节点(pnode)
5.更新"屁股节点"-------让"屁股节点"指针指向新节点(pq->rear = pnew;)
6.更新项数;

- (2)删除项数的操作:通过创建节点指针,让这个指针指向要删除的节点,删除这个指针所指向的内容即可
其中将节点中项部分的内容取出(我感觉这里这么做只是为了做个删除备份)用到了辅助函数:

static void CopyToItem(Node*pn, Item*item)
{
	*item = pn->item;
}

辅助函数是把要删除的节点(pn)中的项(pn->item)做个备份(让item指向这个数据)(注意这里不是地址传递而是值传递)
这个函数的操作流程是:
1.创建一个指向节点结构的指针(pt)------作用类似于"current"指针
2.对队列的情况的判断-----空的就无法执行操作
3.对前指针进行备份,转移处理:
(1)备份:(把第一个节点的项的内容复制一下)
(2)转移:让pt和前指针指向同一个节点(形成current"节点")------pt = pq->front;
再让前指针指向前指针的"下一个"从而形成转移--------pq->front = pq->front->next;
4.释放pt指针所指向的节点
5.项数的改变
6.如果项数为0了,队列的尾部(pq->rear"后指针")要指向空(注意"后指针"和"后指针的尾巴",前者是有实际节点的,后者一般为null).

- (3)清空处理:就是对每个节点进行删除操作

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bussyman

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值