#include "stdio.h"
#include "stdlib.h"
typedef int ElemType;
//值节点--多个
typedef struct Node
{
ElemType data;//存储队列的元素值
struct Node *next;//存储下一个元素节点的地址
}DataNode;
//头节点--1个
typedef struct
{
DataNode* front;//存储队头元素节点的地址 (队首指针)
DataNode* rear;//存储队尾元素节点的地址 (队尾指针)
}LinkQueue;
//链表初始化
LinkQueue * InitQueue(LinkQueue* Q);
//出队操作
int deQueue(LinkQueue *Q,ElemType *e);
//销毁队列,删除所有链队节点和数据节点
void DestroyQueue(LinkQueue *Q);
//判断队列为空
int QueueEmpty(LinkQueue *Q);
//录入数据
void EnQueue(LinkQueue *Q,ElemType e);
//求队列长度
int lenghtLinkQueue(LinkQueue *Q);
//打印队列中的元素
void DispQueue(LinkQueue *Q);
//根据下标插入元素操作,下标从1开始
int Insertdata(LinkQueue* Q,int count,ElemType e);
//根据下标删除元素操作,下标从1开始
int Deletedata(LinkQueue* Q,int count);
int main(){
int count = 0;
ElemType e;
LinkQueue *Q = NULL;
Q = InitQueue(Q);
printf("输入数据(0:结束):\n");
scanf("%d",&e);
while(e!=0){
EnQueue(Q,e);
scanf("%d",&e);
}
DispQueue(Q);
printf("插入元素操作:\n");
printf("请输入插入元素的位置:");
scanf("%d",&count);
while(count<1||count > lenghtLinkQueue(Q)+1){
printf("输入位置超过队列的长度,当前队列的长度为%d\n,请重新输入:",lenghtLinkQueue(Q));
scanf("%d",&count);
}
printf("请输入插入的数据的数据值:");
scanf("%d",&e);
if(!Insertdata(Q,count,e)) printf("插入失败。\n");
DispQueue(Q);
printf("删除元素操作:\n");
printf("请输入删除元素的位置:");
scanf("%d",&count);
while(count<1||count > lenghtLinkQueue(Q)){
printf("输入位置超过队列的长度,当前队列的长度为%d\n,请重新输入:",lenghtLinkQueue(Q));
scanf("%d",&count);
}
Deletedata(Q,count);
DispQueue(Q);
DestroyQueue(Q);
}
//链表初始化
LinkQueue* InitQueue(LinkQueue* Q)
{
Q=(LinkQueue *)malloc(sizeof(LinkQueue));
Q->front=NULL;
Q->rear=NULL;
return Q;
}
//出队操作
/*
若队列非空,出队,返回1;
否则,提示,返回0
*/
int deQueue(LinkQueue *Q,ElemType *e)
{
DataNode *t;
if(Q->front!=NULL||Q->rear!=NULL)//非空
{
//1.让t指向队头元素节点
t=Q->front;
//2.把队头元素存储到*e中
*e=t->data;
//3.删除队头元素节点
if(Q->front->next==NULL)//只有1个元素
{
/*只有1个元素*/
Q->front=NULL;
Q->rear=NULL;
}
else
{
/*多于1个元素*/
Q->front=t->next;
}
//4.释放t所占的存储空间
free(t);
return 1;
}
else
{
printf("队空,不能出队!\n");
return 0;
}
}
//销毁队列,删除所有链队节点和数据节点
void DestroyQueue(LinkQueue *Q)
{
ElemType e;
while(Q->front!=NULL||Q->rear!=NULL)//非空
{
//出队
deQueue(Q,&e);
}
free(Q);
}
//判断队列为空
/*链式队列中,判断队列是否为空,只需要判断q->front==NULL && q->rear==NULL的条件成立即可*/
int QueueEmpty(LinkQueue *Q)
{
if(Q->front==NULL && Q->rear==NULL)
{
return 1;
}
else
{
return 0;
}
}
//入队操作
/*构造一个节点t,data域存储e,next域存储NULL,若原链队为空,
则将链队结点的两个域都指向结点t,否则将结点t链接到单链表末尾,
并让链队结点的rear域指向它*/
void EnQueue(LinkQueue *Q,ElemType e)
{
DataNode *t;
//1.构造一个节点t,data域存储e,next域存储NULL
t=(DataNode *)malloc(sizeof(DataNode));
t->data=e;
t->next=NULL;
//2.添加
if(Q->front!=NULL||Q->rear!=NULL)//非空
{
/*队非空*/
Q->rear->next=t;
Q->rear=t;
}
else
{
/*队空 */
Q->front=t;
Q->rear=t;
}
}
//求队列长度
/*
求链式队列的长度
*/
int lenghtLinkQueue(LinkQueue *Q)
{
int len;
if (QueueEmpty(Q))
{
len = 0;
return len;
}
DataNode *t;
//1.构造一个节点t,让它指向队首元素front
t=(DataNode *)malloc(sizeof(DataNode));
t=Q->front;
len = 1;
while(t->next != NULL)
{
len++;
t = t->next;
}
return len;
}
//打印队列中的元素
void DispQueue(LinkQueue *Q)
{
DataNode *p;
p=Q->front;
printf("队列元素为:");
while(p!=NULL)
{
printf("%d ",p->data);
p=p->next;
}
printf("\n");
}
//根据下标插入元素,下标从1开始
int Insertdata(LinkQueue* Q,int count,ElemType e){
if(QueueEmpty(Q)){
printf("队列为空,插入失败。\n");
return 0; //插入失败,返回0
}
DataNode* p = Q->front;
DataNode* f = (DataNode *)malloc(sizeof(DataNode));
f->data = e;
if(count == 1){ //如果插入元素的下标为1,先让插入元素的指针域指向队列头指针,再让队列头指针等于插入元素的节点
f->next = p;
Q->front = f;
return 1;
}
for(int i = 1;i < count-1;i++){ //先让数据指针p指向要插入元素下标的上一个节点
p = p->next;
}
f->next = p->next; //先让插入元素的指针域指向数据指针的指针域,再让数据指针的指针域指向插入元素的节点,
p->next = f;
if(count ==lenghtLinkQueue(Q)+1) //如果插入元素的下标为队列的最末尾,让队列尾指针指向插入元素的节点
Q->rear = f;
return 1; //成功删除,返回1
}
//根据下标删除元素,下标从1开始
int Deletedata(LinkQueue* Q,int count){
if(QueueEmpty(Q)){
printf("队列为空,删除失败。\n");
return 0; //插入失败,返回0
}
DataNode *p = Q->front,*temp = NULL; //用p指向当前队列头指针的节点
if(count == 1){
Q->front = Q->front->next; //如果要删除第一个元素,将队列头指针指向下一个节点
free(p); //释放之前头结点的空间
return 1; //成功删除,返回1
}
for(int i = 1;i < count-1;i++){ //将指针p指向要删除元素的上一个节点
p = p->next;
}
temp = p->next; //用temp存储删除元素的指针
p->next=p->next->next; //p的指针域指向删除元素的指针域
free(temp); //释放空间
if(count == lenghtLinkQueue(Q)) Q->rear = p; //如果删除的元素为最后一个元素,将队列尾指针指向p,此时p指向的节点为队列最后一个元素
return 1; //成功删除,返回1
}