队列的顺序存储与链式存储

131 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第21天,点击查看活动详情

1、队列

队列和栈一样是特殊的线性表,它只允许队尾插入,队首删除。就和问我们在窗口排队一样,先来后到。所以很明显,队列可以用解决类似于排队这类问题。

2、顺序存储结构

#define MAXSIZE 100//最大容量
typedef int DataType;//可以是自定义数据类型
typedef struct
{
	DataType Data[MAXSIZE];//队列的存储空间
	int front, rear;//队头与队尾指针,front rear 是下标。
}SeqQueue,*PSeqQueue;

1、队列初始化

PSeqQueue Init_SeqQueue()
{//初始化一个新队列,入口参数:无  ,返回值:新顺序队列指针,null表示失败
	PSeqQueue Q;
	Q = (PSeqQueue)malloc(sizeof(SeqQueue));//在堆区开辟空间
	if (Q)
	{
		Q->front = 0;//初始为空对
		Q->rear = 0;//初始为空对
	}
	return Q;//创建成功
}

2、判队空

int Empty_SeQueue(PSeqQueue Q)
{
	if (Q&&Q->front == Q->rear)
		return 1;//队列为空
	else
            if (!Q) return -1;//队列不存在
		else
                    return 0;//队列非空
}

3、入队

int In_SeqQueue(PSeqQueue Q,DataType x)//入队元素是DataType x
{
	if ((Q->rear + 1) % MAXSIZE == Q->front)//判断队满
	{
		printf("队满!");
		return -1;//队满不能入队
	}
	else
	{
		Q->rear = (Q->rear + 1) % MAXSIZE;//干嘛取余啊???跟没取一样
		Q->Data[Q->rear] = x;//Q->front位置没有使用
		return 1;//入队完成
	}
}

4、出队

int Out_SeqQueue(PSeqQueue Q, DataType *x)
{
	if (Empty_SeQueue(Q))
	{
		printf("队空!");
		return - 1;//队空,不能出队
	}
	else
	{
		Q->front = (Q->front + 1) % MAXSIZE;//Q->front 后移,原位置出队
		*x = Q->Data[Q->front];//x等于队头元素
		return 1;//出队成功
	}
}

5、读队头元素

int Front_SeqQueue(PSeqQueue Q, DataType *x)
{
	if (Empty_SeQueue(Q))
	{
		printf("队空!");
		return -1;//队空,不能得到队头元素
	}
	else
	{
		*x = Q->Data[(Q->front + 1) % MAXSIZE];//front rear 用来控制下标
		return 1;//取对头元素完成
	}
}

销毁队列

void Destory_SeqQueue(PSeqQueue *Q)//地址传递
{
	if (*Q)//释放一次队列
		free(*Q);
	*Q = NULL;//释放一次临时的PSeqQueue变量
}

2、队列的链表存储方式

typedef struct node//节点的结构
{
	DataType Data;
	struct node* next;
}Qnode,*PQNode;
//队头队尾指针
typedef struct
{
	PQNode front, rear;
}LinkQueue,*PLinkQueue;

1、初始化队列

PLinkQueue Init_LinkQueue()
{
	PLinkQueue Q;
	Q = (PLinkQueue)malloc(sizeof(LinkQueue));
	if (Q)
	{
		Q->front = NULL;
		Q->rear = NULL;//顺序存储这里是令其等于0
	}
	return Q;
}

2、判队空

int Empty_LinkQueue(PLinkQueue Q)
{
	if (Q&&Q->front == NULL && Q->rear == NULL)
		return 1;
	else
		return 0; 
}

3、入队

PSeqQueue In_LinkQueue(PLinkQueue Q,DataType x)
{
	PQNode p;//节点
        
	p = (PQNode)malloc(sizeof(Qnode));
	if (!p)
	{
		printf("内存溢出");
		return 0;
	}
	p->Data = x;
	p->next = NULL;
        
	if (Empty_LinkQueue(Q))//如果为空,入队的是第一个元素,要担任来连接front和rear的责任
	{
		Q->rear = Q->front = p;//和顺序存储不同,这个对头存储了数据
	}
	else//入队的不是第一个元素,将其挂在rear上,rear后移
	{
		Q->rear->next = p;
		Q->rear = p;
	}
	return 1;
}

4、出队

int Out_LinkQueue(PLinkQueue Q,DataType *x)
{
	PQNode p;
	if (Empty_LinkQueue(Q))//如果为空
	{
		printf("队空!");
		return 0;//队空不能出队
	}
	else
	{
		*x = Q->front->Data;//和顺序存储不同,这个对头存储了数据
		p = Q->front;//你不多此一举这条语句????
		Q->front = Q->front->next;
		free(p);//何必多此一举????上句不用P
		if (!Q->front)//释放队头节点
			Q->rear = NULL;
		return 1;//出队完成
	}
}

5、取队头

int Front_LinkQueue(PLinkQueue Q, DataType *x)
{
	PQNode p;
	if (Empty_LinkQueue(Q))
	{
		printf("队空!");
		return 0;//队空不能出队
	}
	else
	{
		*x = Q->front->Data;
		return 1;//出队完成
	}
}

6、销毁

void Destroy_LinkQueue(PLinkQueue Q)//??
{
	PQNode p;
	if (Q)
	{
		while (Q->front)//队中元素依次释放
		{
			p = Q->front;
			Q->front = Q->front->next;
			free(p);
		}
		free(Q);
	}
	p = NULL;
}