附加头结点实现循环队列

typedef struct node{
	int data;
	struct node *next;
}*list,lnode;

约定:附加头结点的data用于储存队列中有几个节点(不包括附加头结点),另设尾指针rear,指向队列的最后一个节点,当队列为空时,rear指向附加头结点,rear->next = rear;当队列不为空时,rear所指节点的下一个是附加头结点,附加头结点的下一个才是队列的真正的头结点。

由于使用了附加头结点的data统计队列的长度,因此把求队列长度这一操作的时间复杂度从O(n)降到了O(1),在统计时候,只需要返回rear->next->data;即可

插入操作:

void insert(list &sq,int x){
	
	list new = (list)malloc(sizeof(lnode));
	
	new->data = x;
	new->next = rear->next;//把附加头结点先记在新节点中 
	rear->next = new;//把新节点加入到队列尾部 
	rear = new;//尾指针指向新的尾结点 
	rear->next->data ++;//这一步很容易忘 
} 

判空,求长度,打印等比较简单,在这里就不再赘述

唯一有点小小问题的点在于删除操作,这里有个小坑

bool del(list &sq,int &item){//假设要把删除节点的值通过item返回 

	if(rear->next->data == 0){//删除操作嘛,肯定要先看看队列是不是空的 
		printf("error");
		return false;
	}
	else{
		list exhead = rear->next;//附加头结点 
		list head = rear->next->next;//真正队列中的第一个节点
        item = head->data;
		exhead->next = head->next;
		exhead->data --;
		free(head);//养成好习惯,不用了及时释放掉 
	}
    return true;
}

按照我们一般的思路写到这肯定是没有问题的,但是没有问题就是最大的问题,这时候就会出现一种很神奇的情况,正常的插入删除都没问题,但是唯独把链表删空了之后,再进行插入就有问题了,我们会很神奇的发现链表的长度是对的,但是打印链表的时候,无论实际有几个点,只会输出一个点的data值,这到底是为什么呢?看到这,请先自己小小思考一会                 

 

想出来了,那么恭喜

 没想出来,也没关系,我们一起来想

因为这时候统计队列长度只是通过返回rear->next->data实现的,并不会遍历整个链表,而且只会有一个值能进行输出,我们不妨大胆猜想,是不是链表断掉了,而且这种情况只会发生于在链表被删空之后,所以说问题就应当是在删除最后一个节点的时候产生的

我们来手动模拟一下

按照上面的操作, exhead正常指向附加头结点,head指向头结点,修改附加头结点的指针域,指向附加头结点自己,这时候我们发现并没有问题,附加头结点的data变成了0,而且指向自己,这不就跟初始化链表时候一样吗?真的完全一样吗?

整个链表的位置我们是通过rear获取的,要按说删空了之后,rear应该指向了附加头结点啊,但是这里并没有,所以说我们前面的问题也就能解释通了,那么如何解决呢?个人认为最简单的方式就是在只有一个节点的时候进行特判,直接进行一遍初始化就行了

if(rear->next->data == 1){
	list nouse = rear->next;
	item = rear->data;
	rear->data = 0;
	rear->next = rear;
	free(nouse);
} 

到站下车,感谢您的观看,谢谢了您馁

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值