队列的链式存储实现

一、定义两个个结构体


#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef int ElemType;    // 自定义队列的数据元素为整数。

typedef struct LNode
{
  ElemType data;         // 存储队列中的元素。
  struct LNode *next;    // next指针。
}LNode;

typedef struct
{
  LNode *front,*rear;     // 队列的头指针和尾指针。
}LinkQueue,*PLinkQueue;

int main()
{
  return 0;
}

二、创建队列并初始化

// 队列QQ的初始化操作。
int InitQueue(PLinkQueue QQ);           

int main()
{
  LinkQueue QQ;     // 创建队列。

  memset(&QQ,0,sizeof(LinkQueue));

  InitQueue(&QQ);  // 初始化队列。
  return 0;
}

// 初始化队列,返回值:0-失败;1-成功。
int InitQueue(PLinkQueue QQ)
{
  LNode *head = (LNode *)malloc(sizeof(LNode));  // 分配头结点。

  if (head == NULL) return 0;  // 内存不足,返回失败。

  head->next=NULL;  // 头结点的下一结点暂时不存在,置空。

  QQ->front=QQ->rear=head;

  return 1;
}

三、创建一个元素

int main()
{
  LinkQueue QQ;     // 创建队列。

  memset(&QQ,0,sizeof(LinkQueue));

  InitQueue(&QQ);  // 初始化队列。

  ElemType ee;     // 创建一个数据元素。

  return 0;
}

四、队列长度

// 求队列的长度,返回值:>=0-队列QQ元素的个数。
int  Length(PLinkQueue QQ);          

int main()
{
  LinkQueue QQ;     // 创建队列。

  memset(&QQ,0,sizeof(LinkQueue));

  InitQueue(&QQ);  // 初始化队列。

  ElemType ee;     // 创建一个数据元素。

  printf("队列的长度是%d\n",Length(&QQ));

  return 0;
}

// 求队列的长度,返回值:>=0-队列QQ元素的个数。
int Length(PLinkQueue QQ)
{
  if (QQ == NULL) return 0;  // 检查空指针。

  if (QQ->front == NULL) { printf("队列QQ未初始化。\n"); return 0; } // 队列未初始化。

  LNode *pp=QQ->front->next;  // 头结点不算,从第1个结点开始。

  int length=0;

  while (pp != NULL) { pp=pp->next; length++; }

  return length;

}

五、入队

// 元素入队,返回值:0-失败;1-成功。
int InQueue(PLinkQueue QQ, ElemType *ee);

int main()
{
  LinkQueue QQ;     // 创建队列。

  memset(&QQ,0,sizeof(LinkQueue));

  InitQueue(&QQ);  // 初始化队列。

  ElemType ee;     // 创建一个数据元素。

  printf("元素(1、2、3、4、5、6、7、8、9、10)入队。\n");
  ee=1;  InQueue(&QQ, &ee);
  ee=2;  InQueue(&QQ, &ee);
  ee=3;  InQueue(&QQ, &ee);
  ee=4;  InQueue(&QQ, &ee);
  ee=5;  InQueue(&QQ, &ee);
  ee=6;  InQueue(&QQ, &ee);
  ee=7;  InQueue(&QQ, &ee);
  ee=8;  InQueue(&QQ, &ee);
  ee=9;  InQueue(&QQ, &ee);
  ee=10; InQueue(&QQ, &ee);

  printf("队列的长度是%d\n",Length(&QQ));

  return 0;
}

// 元素入队,返回值:0-失败;1-成功。
int InQueue(PLinkQueue QQ, ElemType *ee)
{
  if ( (QQ == NULL) || (ee == NULL) ) return 0;   // 检查空指针。

  if (QQ->front == NULL) { printf("队列QQ未初始化。\n"); return 0; } // 队列未初始化。

  LNode *tmp = (LNode *)malloc(sizeof(LNode));  // 分配一个结点。
  if (tmp == NULL) return 0;  // 内存不足,返回失败。

  // 考虑数据元素为结构体的情况,这里采用了memcpy的方法而不是直接赋值。
  memcpy(&tmp->data,ee,sizeof(ElemType));
  tmp->next=NULL;

  // 把tmp追加到QQ->rear之后。
  QQ->rear->next=tmp;
  QQ->rear=tmp;

  return 1;
}

六、查看队列元素

// 打印队列中全部的元素。
void PrintQueue(PLinkQueue QQ);         

int main()
{
  LinkQueue QQ;     // 创建队列。

  memset(&QQ,0,sizeof(LinkQueue));

  InitQueue(&QQ);  // 初始化队列。

  ElemType ee;     // 创建一个数据元素。

  printf("元素(1、2、3、4、5、6、7、8、9、10)入队。\n");
  ee=1;  InQueue(&QQ, &ee);
  ee=2;  InQueue(&QQ, &ee);
  ee=3;  InQueue(&QQ, &ee);
  ee=4;  InQueue(&QQ, &ee);
  ee=5;  InQueue(&QQ, &ee);
  ee=6;  InQueue(&QQ, &ee);
  ee=7;  InQueue(&QQ, &ee);
  ee=8;  InQueue(&QQ, &ee);
  ee=9;  InQueue(&QQ, &ee);
  ee=10; InQueue(&QQ, &ee);

  printf("队列的长度是%d\n",Length(&QQ));

  PrintQueue(&QQ);

  return 0;
}

// 打印队列中全部的元素。
void PrintQueue(PLinkQueue QQ)
{
  if (QQ == NULL) return;   // 检查空指针。

  if (QQ->front == NULL) { printf("队列QQ未初始化。\n"); return; } // 队列未初始化。

  LNode *pp=QQ->front->next;  // 从第1个数据结点开始。

  while (pp != NULL)
  {
    printf("%-3d", pp->data);  // 如果元素ee为结构体,这行代码要修改。
    pp=pp->next;
  }

  printf("\n");
}

七、出队

// 元素出队,返回值:0-失败;1-成功。
int OutQueue(PLinkQueue QQ, ElemType *ee);

// 判断队列是否为空,返回值:1-空,0-非空或失败。
int  IsEmpty(PLinkQueue QQ);         

int main()
{
  LinkQueue QQ;     // 创建队列。

  memset(&QQ,0,sizeof(LinkQueue));

  InitQueue(&QQ);  // 初始化队列。

  ElemType ee;     // 创建一个数据元素。

  printf("元素(1、2、3、4、5、6、7、8、9、10)入队。\n");
  ee=1;  InQueue(&QQ, &ee);
  ee=2;  InQueue(&QQ, &ee);
  ee=3;  InQueue(&QQ, &ee);
  ee=4;  InQueue(&QQ, &ee);
  ee=5;  InQueue(&QQ, &ee);
  ee=6;  InQueue(&QQ, &ee);
  ee=7;  InQueue(&QQ, &ee);
  ee=8;  InQueue(&QQ, &ee);
  ee=9;  InQueue(&QQ, &ee);
  ee=10; InQueue(&QQ, &ee);

  printf("队列的长度是%d\n",Length(&QQ));

  PrintQueue(&QQ);

  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);
  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);
  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);
  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);
  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);
  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);
  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);

  printf("队列的长度是%d\n",Length(&QQ));
  PrintQueue(&QQ);

  return 0;
}

// 判断队列是否为空,返回值:1-空,0-非空或失败。
int IsEmpty(PLinkQueue QQ)
{
  if (QQ == NULL) return 0;  // 检查空指针。

  if (QQ->front == NULL) { printf("队列QQ未初始化。\n"); return 0; } // 队列未初始化。

  if (QQ->front->next == NULL) return 1;

  return 0;
}

// 元素出队,返回值:0-失败;1-成功。
int OutQueue(PLinkQueue QQ, ElemType *ee)
{
  if ( (QQ == NULL) || (ee == NULL) ) return 0;   // 检查空指针。

  if (QQ->front == NULL) { printf("队列QQ未初始化。\n"); return 0; } // 队列未初始化。

  if (IsEmpty(QQ) == 1) { printf("队列为空。\n"); return 0; }

  LNode *tmp=QQ->front->next;

  memcpy(ee,&tmp->data,sizeof(ElemType));  
  QQ->front->next=tmp->next;

  // 如果出队的是最后一个结点。
  if (QQ->rear==tmp) QQ->rear=QQ->front;
  
  free(tmp);

  return 1;
}

八、查看队头元素

// 获取队头元素,返回值:0-失败;1-成功。
// 只查看队头元素的值,元素不出队。
int GetHead(PLinkQueue QQ, ElemType *ee);

int main()
{
  LinkQueue QQ;     // 创建队列。

  memset(&QQ,0,sizeof(LinkQueue));

  InitQueue(&QQ);  // 初始化队列。

  ElemType ee;     // 创建一个数据元素。

  printf("元素(1、2、3、4、5、6、7、8、9、10)入队。\n");
  ee=1;  InQueue(&QQ, &ee);
  ee=2;  InQueue(&QQ, &ee);
  ee=3;  InQueue(&QQ, &ee);
  ee=4;  InQueue(&QQ, &ee);
  ee=5;  InQueue(&QQ, &ee);
  ee=6;  InQueue(&QQ, &ee);
  ee=7;  InQueue(&QQ, &ee);
  ee=8;  InQueue(&QQ, &ee);
  ee=9;  InQueue(&QQ, &ee);
  ee=10; InQueue(&QQ, &ee);

  printf("队列的长度是%d\n",Length(&QQ));

  // 只查看队头元素的值,元素不出队。
  if (GetHead(&QQ,&ee)==1)  printf("队头的元素值为%d\n",ee);

  return 0;
}

// 获取队头元素,返回值:0-失败;1-成功。
// 只查看队头元素的值,元素不出队。
int GetHead(PLinkQueue QQ, ElemType *ee)
{
  if ( (QQ == NULL) || (ee == NULL) ) return 0;   // 检查空指针。

  if (QQ->front == NULL) { printf("队列QQ未初始化。\n"); return 0; } // 队列未初始化。

  if (IsEmpty(QQ) == 1) { printf("队列为空。\n"); return 0; }

  memcpy(ee,&QQ->front->next->data,sizeof(ElemType));  

  return 1;
}


九、销毁队列

// 销毁队列QQ。
void DestroyQueue(PLinkQueue QQ);

int main()
{
  LinkQueue QQ;     // 创建队列。

  memset(&QQ,0,sizeof(LinkQueue));

  InitQueue(&QQ);  // 初始化队列。

  ElemType ee;     // 创建一个数据元素。

  printf("元素(1、2、3、4、5、6、7、8、9、10)入队。\n");
  ee=1;  InQueue(&QQ, &ee);
  ee=2;  InQueue(&QQ, &ee);
  ee=3;  InQueue(&QQ, &ee);
  ee=4;  InQueue(&QQ, &ee);
  ee=5;  InQueue(&QQ, &ee);
  ee=6;  InQueue(&QQ, &ee);
  ee=7;  InQueue(&QQ, &ee);
  ee=8;  InQueue(&QQ, &ee);
  ee=9;  InQueue(&QQ, &ee);
  ee=10; InQueue(&QQ, &ee);

  printf("队列的长度是%d\n",Length(&QQ));

  // 只查看队头元素的值,元素不出队。
  if (GetHead(&QQ,&ee)==1)  printf("队头的元素值为%d\n",ee);

  DestroyQueue(&QQ); // 销毁队列QQ。

  printf("队列的长度是%d\n",Length(&QQ));

  return 0;
}

// 销毁队列QQ。
void DestroyQueue(PLinkQueue QQ)
{
  if (QQ == NULL) return;    // 检查空指针。

  // 销毁队列QQ是指释放链表全部的结点,包括头结点。
  LNode *tmp=QQ->front,*tmpnext;

  while(tmp!=NULL)
  {
    tmpnext=tmp->next;  // tmpnext保存下一结点的地址。
    free(tmp);          // 释放当前结点。
    tmp=tmpnext;        // tmp指针移动到下一结点。
  }

  QQ->front=QQ->rear=NULL;  // 防止野指针。

  return;
}

十、完整代码

/*
 * 程序名:linkqueue1.c,此程序演示队列的链表实现(带头结点)。
 * 作者:C语言技术网(www.freecplus.net) 日期:20201230
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef int ElemType;    // 自定义队列的数据元素为整数。

typedef struct LNode
{
  ElemType data;         // 存储队列中的元素。
  struct LNode *next;    // next指针。
}LNode;

typedef struct
{
  LNode *front,*rear;     // 队列的头指针和尾指针。
}LinkQueue,*PLinkQueue;

// 队列QQ的初始化操作。
int InitQueue(PLinkQueue QQ);                     

// 销毁队列QQ。
void DestroyQueue(PLinkQueue QQ);

// 清空队列。
void Clear(PLinkQueue QQ);                    

// 元素入队,返回值:0-失败;1-成功。
int InQueue(PLinkQueue QQ, ElemType *ee);

// 打印队列中全部的元素。
void PrintQueue(PLinkQueue QQ);                    

// 求队列的长度,返回值:>=0-队列QQ元素的个数。
int  Length(PLinkQueue QQ);                   

// 判断队列是否已满,链式队列不存在队满的说法。
int IsFull(PLinkQueue QQ);

// 判断队列是否为空,返回值:1-空,0-非空或失败。
int  IsEmpty(PLinkQueue QQ);                    

// 元素出队,返回值:0-失败;1-成功。
int OutQueue(PLinkQueue QQ, ElemType *ee);

// 获取队头元素,返回值:0-失败;1-成功。
// 只查看队头元素的值,元素不出队。
int GetHead(PLinkQueue QQ, ElemType *ee);

int main()
{
  LinkQueue QQ;     // 创建队列。

  memset(&QQ,0,sizeof(LinkQueue));

  InitQueue(&QQ);  // 初始化队列。

  ElemType ee;     // 创建一个数据元素。

  printf("元素(1、2、3、4、5、6、7、8、9、10)入队。\n");
  ee=1;  InQueue(&QQ, &ee);
  ee=2;  InQueue(&QQ, &ee);
  ee=3;  InQueue(&QQ, &ee);
  ee=4;  InQueue(&QQ, &ee);
  ee=5;  InQueue(&QQ, &ee);
  ee=6;  InQueue(&QQ, &ee);
  ee=7;  InQueue(&QQ, &ee);
  ee=8;  InQueue(&QQ, &ee);
  ee=9;  InQueue(&QQ, &ee);
  ee=10; InQueue(&QQ, &ee);

  printf("队列的长度是%d\n",Length(&QQ));

  PrintQueue(&QQ);

  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);
  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);
  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);
  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);
  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);
  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);
  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);

  printf("队列的长度是%d\n",Length(&QQ));
  PrintQueue(&QQ);

  printf("元素(11、12、13、14、15)入队。\n");
  ee=11;  InQueue(&QQ, &ee);
  ee=12;  InQueue(&QQ, &ee);
  ee=13;  InQueue(&QQ, &ee);
  ee=14;  InQueue(&QQ, &ee);
  ee=15;  InQueue(&QQ, &ee);

  printf("队列的长度是%d\n",Length(&QQ));

  PrintQueue(&QQ);

  // 只查看队头元素的值,元素不出队。
  if (GetHead(&QQ,&ee)==1)  printf("队头的元素值为%d\n",ee);

  DestroyQueue(&QQ); // 销毁队列QQ。

  return 0;
}

// 初始化队列,返回值:0-失败;1-成功。
int InitQueue(PLinkQueue QQ)
{
  LNode *head = (LNode *)malloc(sizeof(LNode));  // 分配头结点。

  if (head == NULL) return 0;  // 内存不足,返回失败。

  head->next=NULL;  // 头结点的下一结点暂时不存在,置空。

  QQ->front=QQ->rear=head;

  return 1;
}

// 清空队列。
void Clear(PLinkQueue QQ)
{
  if (QQ == NULL) return; // 判断队列是否存在。

  if (QQ->front == NULL) { printf("队列QQ未初始化。\n"); return; } // 队列未初始化。

  // 清空队列QQ是指释放链表全部的数据结点,但保留头结点。
  LNode *tmp=QQ->front->next,*tmpnext;

  while(tmp!=NULL)
  {
    tmpnext=tmp->next;  // tmpnext保存下一结点的地址。
    free(tmp);          // 释放当前结点。
    tmp=tmpnext;        // tmp指针移动到下一结点。
  }

  QQ->rear=QQ->front;   // 尾指针指向头结点。

  QQ->front->next=NULL;
}

// 求队列的长度,返回值:>=0-队列QQ元素的个数。
int Length(PLinkQueue QQ)
{
  if (QQ == NULL) return 0;  // 检查空指针。

  if (QQ->front == NULL) { printf("队列QQ未初始化。\n"); return 0; } // 队列未初始化。

  LNode *pp=QQ->front->next;  // 头结点不算,从第1个结点开始。

  int length=0;

  while (pp != NULL) { pp=pp->next; length++; }

  return length;

}

// 销毁队列QQ。
void DestroyQueue(PLinkQueue QQ)
{
  if (QQ == NULL) return;    // 检查空指针。

  // 销毁队列QQ是指释放链表全部的结点,包括头结点。
  LNode *tmp=QQ->front,*tmpnext;

  while(tmp!=NULL)
  {
    tmpnext=tmp->next;  // tmpnext保存下一结点的地址。
    free(tmp);          // 释放当前结点。
    tmp=tmpnext;        // tmp指针移动到下一结点。
  }

  QQ->front=QQ->rear=NULL;  // 防止野指针。

  return;
}

// 判断队列是否为空,返回值:1-空,0-非空或失败。
int IsEmpty(PLinkQueue QQ)
{
  if (QQ == NULL) return 0;  // 检查空指针。

  if (QQ->front == NULL) { printf("队列QQ未初始化。\n"); return 0; } // 队列未初始化。

  if (QQ->front->next == NULL) return 1;

  return 0;
}

// 判断队列是否已满,链式队列不存在队满的说法。
int IsFull(PLinkQueue QQ)
{
  if (QQ == NULL) return 0;   // 检查空指针。

  return 1;
}

// 元素入队,返回值:0-失败;1-成功。
int InQueue(PLinkQueue QQ, ElemType *ee)
{
  if ( (QQ == NULL) || (ee == NULL) ) return 0;   // 检查空指针。

  if (QQ->front == NULL) { printf("队列QQ未初始化。\n"); return 0; } // 队列未初始化。

  LNode *tmp = (LNode *)malloc(sizeof(LNode));  // 分配一个结点。
  if (tmp == NULL) return 0;  // 内存不足,返回失败。

  // 考虑数据元素为结构体的情况,这里采用了memcpy的方法而不是直接赋值。
  memcpy(&tmp->data,ee,sizeof(ElemType));
  tmp->next=NULL;

  // 把tmp追加到QQ->rear之后。
  QQ->rear->next=tmp;
  QQ->rear=tmp;

  return 1;
}

// 打印队列中全部的元素。
void PrintQueue(PLinkQueue QQ)
{
  if (QQ == NULL) return;   // 检查空指针。

  if (QQ->front == NULL) { printf("队列QQ未初始化。\n"); return; } // 队列未初始化。

  LNode *pp=QQ->front->next;  // 从第1个数据结点开始。

  while (pp != NULL)
  {
    printf("%-3d", pp->data);  // 如果元素ee为结构体,这行代码要修改。
    pp=pp->next;
  }

  printf("\n");
}

// 元素出队,返回值:0-失败;1-成功。
int OutQueue(PLinkQueue QQ, ElemType *ee)
{
  if ( (QQ == NULL) || (ee == NULL) ) return 0;   // 检查空指针。

  if (QQ->front == NULL) { printf("队列QQ未初始化。\n"); return 0; } // 队列未初始化。

  if (IsEmpty(QQ) == 1) { printf("队列为空。\n"); return 0; }

  LNode *tmp=QQ->front->next;

  memcpy(ee,&tmp->data,sizeof(ElemType));  
  QQ->front->next=tmp->next;

  // 如果出队的是最后一个结点。
  if (QQ->rear==tmp) QQ->rear=QQ->front;
  
  free(tmp);

  return 1;
}

// 获取队头元素,返回值:0-失败;1-成功。
// 只查看队头元素的值,元素不出队。
int GetHead(PLinkQueue QQ, ElemType *ee)
{
  if ( (QQ == NULL) || (ee == NULL) ) return 0;   // 检查空指针。

  if (QQ->front == NULL) { printf("队列QQ未初始化。\n"); return 0; } // 队列未初始化。

  if (IsEmpty(QQ) == 1) { printf("队列为空。\n"); return 0; }

  memcpy(ee,&QQ->front->next->data,sizeof(ElemType));  

  return 1;
}

posted @ 2021-08-02 17:02  lnterpreter  阅读(81)  评论(0编辑  收藏  举报