C语言——栈与队列的实现

栈与队列都是受限的线性表,均可以通过顺序表(数组)和链表两种方式得到实现。只不过栈是FILO,队列是FIFO,即栈和队列在出和入的方式上有所不同。而通过数组和链表实现的区别,即为数组与链表本身的区别:数组的存储空间是连续的,不可动态扩展;链表的存储空间是不连续的,可以动态扩展。下面具体来说。

一、栈的实现:

栈有栈底和栈顶,栈底是固定的,栈顶指向栈最顶上的第一个数据;数据的入栈和出栈只能在栈顶端进行;故只需为栈指定栈顶即可,栈顶的数据类型决定于栈中数据定位的方式。

1.顺序栈:

顺序栈是以数组的方式实现栈,数组是靠索引定位数据,故顺序栈的栈顶与数组索引的类型一致,为int型;

具体的代码实现:

C语言——栈与队列的实现_第1张图片

C语言——栈与队列的实现_第2张图片

C语言——栈与队列的实现_第3张图片

C语言——栈与队列的实现_第4张图片

C语言——栈与队列的实现_第5张图片

 

2.链栈:

链栈是以链表的方式实现栈,链表是靠指针定位数据,故链栈的栈顶与链表指针的类型一致,为链结点的指针;

具体的实现代码:

C语言——栈与队列的实现_第6张图片

C语言——栈与队列的实现_第7张图片

C语言——栈与队列的实现_第8张图片

C语言——栈与队列的实现_第9张图片

C语言——栈与队列的实现_第10张图片

C语言——栈与队列的实现_第11张图片

二、队列的实现:

队列有队首和队尾,在数组队列中,一般大家的做法是:队首指向队列的第一个数据,队尾指向队列最后一个数据的下一个数据;数据的入队只能在队首进行,数据的出队只能在队尾进行;在链队列中,队首指向头结点,队尾指向尾结点;故需分别指定队首和队尾,队首和队尾的数据类型决定于队列中数据定位的方式。

具体的代码实现参考:

http://www.cnblogs.com/kubixuesheng/p/4104802.html

1.顺序队列:

队首和队尾为int类型,对应数组索引;

一般的顺序队列,若队尾的数据出队后,其他数据要到队尾需要进行移动,而数组又不便于数据的移动,故采用循环队列。

在循环队列中:

插入数据后,队首=队首+1应修改为:队首=(队首+1)%队列长度;

删除数据后,队尾=队尾+1应修改为:队尾=(队尾+1)%队列长度;

但在循环队列中,队列为空和队列为满时,队首和队尾的指向是相同的,

C语言——栈与队列的实现_第12张图片

故需加以区分,区分的方式有:

(1)、另设一个布尔变量以区别队列的空和满;

(2)、少用一个元素的空间,约定入队前测试尾指针在循环下加 1 后是否等于头指针,若相等则认为队满;

(3)、使用一个计数器记录队列中元素的总数。

2.链队列:

队首和队尾对应头指针和尾指针;为了操作的方便,在初始化队列时,可以为队列添加一个头结点,判断队列为空的条件时:队首=队尾,指向头节点;

3.个人思考:

对顺序栈、链栈、链队列,栈首、队首、队尾都指向的是该方向的第一个数据;而在循环队列中,队首指向队列第一个数据,队尾指向队列最后一个数据的下一位;形式上不够统一。

所以我的想法是,能不能对循环队列做一个改进,使之在队首、队尾的概念上能与链队列等达成统一;

经过思考,得到的方案是:重新定义队列为空:

队列为空:队首指向队列的第一个空数据;队尾指向队首-1,即队列的最后一个空数据;

这样一来,队列为满时:队首指向队列的第一个数据;队尾指向队列的最后一个数据;符合队首与队尾的定义。不过,队列为空和队列为满,队首和队尾的指向还是相同,需要加以区分,区分的方式:

(1)、另设一个布尔变量以区别队列的空和满;

(2)、使用一个计数器记录队列中元素的总数。

具体实现的代码:

#include 
#include 
#include 

#define SizeOfQueue 6

typedef struct Queue 
{
	int data[SizeOfQueue];
	int head;
	int tail;
	int cnt;
}queue;
queue* queue_init() 
{
	queue* qe = (queue*)malloc(sizeof(queue));
	if (NULL == qe)
	{
		printf("Init queue erroe");
		exit(1);
	}
	memset(qe, 0, sizeof(queue));
	qe->head = 0;
	qe->tail = SizeOfQueue - 1;
	qe->cnt = 0;
	return qe;
};
void en_queue(queue* qe,int data1) 
{
	if (qe->cnt == SizeOfQueue)//判断栈满;
	{
		printf("Queue is full");
		exit(1);
	}
	qe->tail = (qe->tail+1)%SizeOfQueue;
	qe->data[qe->tail] = data1;
	qe->cnt += 1;
};
void de_queue(queue* qe)
{
	int tmp_data;
	if(qe->cnt==0)
	{
		printf("Queue is empty");
		exit(1);
	}//判断栈空
	tmp_data = qe->data[qe->head];
	qe->head = (qe->head + 1) % SizeOfQueue;
	qe->cnt -= 1;
};
int main() 
{
	queue* que;
	que = queue_init();
	int data[5] = {1,2,3,4,5};
	for (int i = 0; i < 5; i++)
	{
		en_queue(que, data[i]);
	}
	de_queue(que);
	de_queue(que);
	en_queue(que, 6);
	en_queue(que, 7);
	en_queue(que, 8);
	en_queue(que, 9);
};

 

你可能感兴趣的:(linux,c,data,structure)