循环队列的动态回收方法c/c++

循环队列的动态回收方法

题目描述

队列的运算特性是先进先出。队列是一种重要的数据类型,队列在各种类型的系统中应
用广泛。讨论队列的结构特征与操作实现特点,有着重要的意义。实现了循环队列存储空间
的动态增长。但是存储空间在开辟并使用后若闲置, 并且用户不能确定在之后的操作中用
到这些闲置空间时,需要想出一种办法将这部分空间回收。设置循环队列闲置空间达到
QUEUE_FREESIZE 时,按 50%的比例回收大小为 UEUE_FREESIZE*50%的这部分空间。
下面给出了部分的初始定义供设计时参考。

# define QUEUE_INIT_SIZE 5 //队列存储空间的初始分配量
# define QUEUE_INCREMENT 5 //队列存储空间的分配增量
# define QUEUE_FREESIZE 10 //队列存储空间的回收预定值
# define PERCENT 0.5 //队列闲置空间的回收比例**
typedef struct //循环队列类型
{
ElementType *element; //初始化的动态分配存储空间
int front; //队头指针, 若队列非空,指向队列头元素
int rear; //队尾指针, 若队列非空,指向队尾元素的下一个位置
int QueueSize; //当前分配的存储空间(以 sizeof(ElementType)为单位)
}SeqQueue;

源代码

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string>
#include <windows.h> 
# define QUEUE_INIT_SIZE 5       //队列存储空间的初始分配量
# define QUEUE_INCREMENT 5  //队列存储空间的分配增量
# define QUEUE_FREESIZE 10      //队列存储空间的回收预定值
# define PERCENT 0.5                  //队列闲置空间的回收比例
#define ElementType int
using namespace std;
typedef struct  //循环队列类型
{
	ElementType* element = NULL;    //一个的数组头指针
	int front;         //队头指针,若队列非空,指向队列头元素
	int rear;       //队尾指针,若队列非空,指向队尾元素的下一个位置
	int QueueSize;     //当前分配的存储空间(以sizeof(ElementType)为单位) ,队列中多余空出来的空间? 
	int QueueLength; //队列长度(有数据的) 
}SeqQueue;
bool InitQueue(SeqQueue* Q)     //构造一个空队列Q
{
	free(Q->element); 
	Q->element = (ElementType*)malloc(QUEUE_INIT_SIZE * sizeof(ElementType));//相当于int element[5];
	if (!Q->element)
		return false;    //内存开辟失败,报告错误并退出程序
	Q->front = Q->rear = 0;
	Q->QueueSize = QUEUE_INIT_SIZE;       //给队列一个初始空间
	Q->QueueLength = 0;
	return true;
}
//int QueueLength(SeqQueue* Q)  //求队列的长度 
//{
//	int n = ((abs((Q->rear) - (Q->front))) % Q->QueueSize) ;
	int n = (Q->rear-Q->front+Q->QueueSize)%Q->QueueSize; 
//	return n;
//}

int ENQueue(SeqQueue* Q, ElementType e)//入队
{
	ElementType* New_Base;// = (ElementType*)malloc(QUEUE_INIT_SIZE * sizeof(ElementType)) 
	
//	if (((Q->rear + 1) % Q->QueueSize) == Q->front) //判断是否队满 
	if(Q->QueueSize <= Q->QueueLength )//判断是否队满
	{
		New_Base = (int*)malloc( (Q->QueueSize + QUEUE_INCREMENT) * sizeof(ElementType));
		if (!New_Base)
			return -1;
			
		for(int i=0;i<Q->QueueSize;i++){ //把值复制过去 
			New_Base[i] = Q->element[i];
		}
		Q->element = New_Base;
		Q->QueueSize += QUEUE_INCREMENT; 
		
		if (Q->rear < Q->front) // section 3 ,右边部分往右移,修改front的值
		{
			int i = Q->QueueSize -QUEUE_INCREMENT - 1; //
			int j = Q->QueueSize   - 1;
			for (; i >= Q->front; i--, j--)
				Q->element[j] = Q->element[i];
		}
//		cout<<"Q->QueueLength"<<Q->QueueLength<<" Q->QueueSize"<<Q->QueueSize<<endl;
		if(Q->QueueLength   == Q->QueueSize - QUEUE_INCREMENT) // 队列满了
		{
			Q->rear =  Q->QueueLength;
		}
			
	}
//	cout<<"###rear:"<<Q->rear<<endl;
	Q->element[Q->rear] = e; //真正的入队 
	Q->QueueLength++; //队列长度加1 
	Q->rear = (Q->rear + 1) % Q->QueueSize; //rear向下移一位 
//	cout<<"front:"<<Q->front<<" rear:"<<Q->rear<<endl;
	return 0;
}

//循环队列中元素的出队操作,出队操作按上面分析结果,实现算法如下:
bool DeleteQueue(SeqQueue* Q)//出队操作的实现算法
{
	int i, j, cnt;
	
	int hsgs = int(QUEUE_FREESIZE * PERCENT);    //回收个数为限定值QUEUE_FREESIZE的50% , 5

	ElementType* newbase;
	if (Q->QueueLength<=0) //Q->rear == Q->front     =-============================!!!!!!!!!!!!
		return false;     //队列为空则报告错误并退出程序
		
	Q->front = (Q->front + 1) % Q->QueueSize;//队头出队 
	Q->QueueLength--;
	
	if (  Q->QueueSize - Q->QueueLength  >= QUEUE_FREESIZE )    //判断闲置空间是否达到定值 ,Q->QueueSize - LEN  >= QUEUE_FREESIZE -1 
	{
		if (Q->front > Q->rear)    //判断队头指针与队尾指针的相对位置,情形3
		{
			for (i = Q->QueueSize - hsgs - 1, j = Q->QueueSize - 1; j >= Q->front; i--, j--)
				Q->element[i] = Q->element[j];    //移动Q->front开始到Q->QueueSize结束的cnt个元素
			
			cnt = Q->QueueSize - Q->front; // 情况三下,右边部分有多少个 
			Q->front = Q->QueueSize - hsgs - cnt;    //修改队头指针
		}
		
		else{
		
			if (Q->QueueSize -(Q->rear )< hsgs)   //判断队尾指针后的闲置空间是否不够回收,情形2 ,Q->QueueSize - (Q->rear + 1) < hsgs
			{
				for (i = 0, j = Q->front; j < Q->rear; i++, j++)
					Q->element[i] = Q->element[j];   //移动所有元素的位置
				Q->front = 0;   //令队头指针指向队列首位置
				Q->rear = Q->front + Q->QueueLength;   //队尾指针指向最后一个元素的后一个位置
			}
		}
		newbase = (ElementType*)realloc(Q->element, (Q->QueueSize - hsgs) * sizeof(ElementType));    //回收空闲空间
		if (!newbase)
			return false;   //内存分配失败,报告错误并退出程序

		Q->element = newbase;
		Q->QueueSize = Q->QueueSize - hsgs;    //修改存储空间的大小
	}
	return true;
}
void meun(){
	cout<<"==========================="<<endl
		<<"| 1. 入队		  |"<<endl
		<<"| 2. 出队      		  |"<<endl
		<<"| 3. 查看队列	  	  |"<<endl 
		<<"| 4. 重置队列	  	  |"<<endl
		<<"| 0. 退出		  |"<<endl
		<<"==========================="<<endl;
}
int main()
{
	int n ;
	ElementType x;
	SeqQueue Q;
	InitQueue(&Q); // 初始化循环队列,并且分配空间
	
	while(true){
		int select;
		system("Cls");
		meun();
		cout<<"请选择: ";
		cin>>select; 
		switch(select){
			case 1:
				cout<<"你要入队几个数据: ";
				cin>>n; // 11
				cout<<"请输入这些数据: ";
				for (int i = 0; i < n; i++)// 入队 
				{
					cin >> x;
					ENQueue(&Q, x); 
				}
				cout<<"* 初始:"<<endl; 
				cout << "队列长度:" <<  Q.QueueLength << endl; //11-7 
				cout << "空闲空间长度:" << Q.QueueSize - Q.QueueLength << endl; // 
				system("pause");
				break;
			case 2:
				cout<<"你要出队几个数据:";
				cin>>n; 
				for(int i=0;i<n;i++){
					DeleteQueue(&Q);
					cout<<"======================"<<endl;
					cout<<"* 出队"<<i+1<<"个后:"<<endl;
					cout << "队列长度:" <<  Q.QueueLength << endl; //
					cout << "空闲空间长度:" << Q.QueueSize - Q.QueueLength << endl; //  
				}
				system("pause");
				break;
			case 3:
				cout<<"//tips: 有效数据外显示@"<<endl;
				cout<<"front:"<<Q.front<<" rear:"<<Q.rear<<endl;
				cout<<"QueueLength:"<<Q.QueueLength<<" QueueSize:"<<Q.QueueSize<<endl;
				if(Q.QueueLength<Q.QueueSize){ // 如果队列没满 
					if(Q.front<= Q.rear) 
						for(int i=0;i<Q.QueueSize;i++){
							if(i>=Q.front && i<=Q.rear-1)
								cout<<Q.element[i]<<" ";
							else cout<<"@ ";
						}
					else 
						for(int i=0;i<Q.QueueSize;i++){
							if(i >= Q.rear && i < Q.front )
								cout<<"@ ";
							else cout<<Q.element[i]<<" ";
						}
				}
				else 
					for(int i=0;i<Q.QueueSize;i++){
						cout<<Q.element[i]<<" ";
					}
				cout<<endl;
//				for(int i=0;i<Q.QueueSize;i++)
//					cout<<Q.element[i]<<" "; 
				system("pause");
				break;
			case 4:
				InitQueue(&Q);
				cout<<"重置完毕!"<<endl;
				system("pause");
				break;
			case 0:
				return 0;
			default:
				cout<<"error! 请重新选择!"<<endl;
				system("pause");
				break;
				
		}
	}

}

最后

在某些频繁入队又出队又入队出队等情况的多种组合下,功能3还是会有bug存在,以后有空再改吧。。。

  • 7
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值