数据结构C实现顺序队列(非循环队列)

2022-08-15 14:47:53

         和栈相反,队列是一种先进先出的的线性表。它只允许在表的一端进行插入,而在另一端删除元素。这和我们日常生活中的队列是一致的,最早进入队列的元素最早离开。在队列中,允许插入的一端叫做队尾,允许删除的一端则稀烂为队头。

         顺序队列,即队列的顺序存储结构。由于队列的队头和队尾的位置均发生变化,因此在队列顺序存储结构中,除了用一组地址连续的存储单元依次存放从队头到队尾的元素之外,还需要附设两个指针front和rear指向队头和队尾元素。

        为了操作方便,在此约定:在非空队列中,队头指针front始终指向队头元素,而队尾rear始终指向队尾元素下一个位置。

      顺序队列的类型描述:

//顺序队列的类型描述
#define MAXSIZE 100
typedef int ElemType;
typedef struct{
	ElemType *data;
	int front,rear;
}SqQueue;


      基本操作:

1. 初始化顺序队列Init_SqQueue(SqQueue* Q):

//初始化顺序队列
void Init_SqQueue(SqQueue* Q){
    Q->data = (SqQueue*)malloc(sizeof(SqQueue) * MAXSIZE);

	Q->front = Q->rear = 0;	
}

2. 销毁顺序队列Destroy_SqQueue(SqQueue* Q)

//销毁顺序队列
void Destroy_SqQueue(SqQueue* Q){
	if(Q->data){
		free(Q->data);
		Q->front = Q->rear = 0;
	}
}

3. 清空顺序队列Clear_SqQueue(SqQueue* Q)

//清空顺序队列
void Clear_SqQueue(SqQueue* Q){
	Q->front = Q->rear = 0;
}

 4. 判断顺序队列是否为空IsEmpty_SqQueue(SqQueue* Q)

//判断顺序队列是否为空
int IsEmpty_SqQueue(SqQueue* Q){
	if(Q->front == Q->rear)
		return 1;
	else{
		return 0;
	}
}

5. 判断顺序队列是否已满iSFull_SqQueue(SqQueue* Q)

//判断顺序队列是否已满
int iSFull_SqQueue(SqQueue* Q){
	if(Q->rear == MAXSIZE)
		return 1;
	else
		return 0;
}

         因为没有设置额外的指针,所以这里判断顺序队列是否已满,实际上是假溢出,并不是真的顺序队列满,原因:

         随着入队,出队的进行,整个队列会整体向后移动,这样就出现队尾指针已经移动到了最后,再有元素入队就会出现队满,即溢出,而事实上此时队中并未真正的满员,这种现象即称为“假溢出”。

6.  求得顺序队列的长度GetLength_SqQueue(SqQueue* Q)

//求得顺序队列的长度
int GetLength_SqQueue(SqQueue* Q){
	return Q->rear - Q->front;
}

7. 取得顺序队列的的队头GetHead_SqQueue(SqQueue* Q,ElemType *x)

//取得顺序队列的的队头
void GetHead_SqQueue(SqQueue* Q,ElemType *x){
	if(IsEmpty_SqQueue(Q)){
		printf("顺序队列空!\n");
		exit(0);
	}
	else{
		*x = Q->data[Q->front];
	}
}

8. 取得顺序队列的的队尾GetRear_SqQueue(SqQueue* Q,ElemType *x)

//取得顺序队列的的队尾
void GetRear_SqQueue(SqQueue* Q,ElemType *x){
	if(IsEmpty_SqQueue(Q)){
		printf("顺序队列空!\n");
		exit(0);
	}
	else{
		*x = Q->data[Q->rear - 1];
	}
}

9. 入顺序队列En_SqQueue(SqQueue* Q,ElemType x)

//入顺序队列
void En_SqQueue(SqQueue* Q,ElemType x){
	if(iSFull_SqQueue(Q)){
		printf("顺序队列已满!\n");
		exit(0);
	}
	else{
		Q->data[Q->rear] = x;
		Q->rear++;
	}	
}


10. 出顺序队列De_SqQueue(SqQueue* Q,ElemType *x)

//出顺序队列
void De_SqQueue(SqQueue* Q,ElemType *x){
	if(IsEmpty_SqQueue(Q)){
		printf("顺序队列空!\n");
		exit(0);
	}
	else{
		*x = Q->data[Q->front];
		Q->front++;
	}	
}

11. 打印顺序队列Print_SqQueue(SqQueue* Q)

//打印顺序队列
void Print_SqQueue(SqQueue* Q){
	int i = Q->front;
	if(IsEmpty_SqQueue(Q)){
		printf("顺序队列空!\n");
		exit(0);
	}
	else{
		while(i < Q->rear)
			printf("%d\t",Q->data[i++]);	
		printf("\n");
	}
}

    说明:

          以上这种顺序队列会出现“假溢出”,随着入队,出队的进行,整个队列会整体向后移动,这样就出现队尾指针已经移动到了最后,再有元素入队就会出现队满,即溢出,而事实上此时队中并未真正的满员。

          为了能充分的利用空间,解决顺序队列的“假溢出”问题,可以采用两种方法:一种是将数据向前移动,让空的存储单元留在队尾;另一种是将顺序队列构造成一个环状的空间,即将队列的数据区data[0....MAXSIZE-1]看成头尾相接的循环结构,使得data[0]接在data[MAXSIZE-1]之后,这就是循环队列。

  • 作者:jesson20121020
  • 原文链接:https://blog.csdn.net/jesson20121020/article/details/39451475
    更新时间:2022-08-15 14:47:53