一、链队的基本操作(明确链队的头指针所指向的结点不使用)
0)链队的定义和一些宏定义
#define MaxSize 100
#define ElementType char//如果要修改数据类型,只需修改这里的宏定义,入队出队的打印,取对头元素,主函数scanf和printf
#define LEN sizeof(QueueNode)
//链队的一个结点
typedef struct QueueNode{
ElementType Data;
struct QueueNode*Next;
}QueueNode,*QueuePointer;
//链队的头指针尾指针,链队的头指针指向的结点数据域为空,也就是少用这个元素的空间
typedef struct{
QueuePointer Head;
QueuePointer Back;
}LinkQueue;
1)链队的初始化---先开辟一个结点,并且在第一次入队操作中不会对第一个结点进行数据域赋值
//初始化
void Init_LinkQueue(LinkQueue* queue){
queue->Head=queue->Back=(QueuePointer)malloc(LEN);
if(queue->Head==NULL){
printf("初始化链队失败!\n");
exit(0);
}
else{
(queue->Head)->Next=NULL;//头指针指向的结点的Next指向空
printf("初始化链队成功!\n");
}
}
2)销毁---包括第一个结点
//销毁,第一个结点也会被释放
void Destroy_LinkQueue(LinkQueue* queue){
QueuePointer Temp;
while(queue->Head!=NULL){
Temp=(queue->Head)->Next;
free(queue->Head);
queue->Head=Temp;
}
if(queue->Head==NULL) printf("\n链队销毁成功!\n");
}
3)入队---明确第一次入队不会对初始化产生的第一个结点进行数据域赋值
//入队,队尾插入,初始化后第一次的入队并不会给第一个结点赋值数据域,而是开辟第二个结点并给其数据域赋值
void Enter_LinkQueue(LinkQueue* queue,ElementType data){
QueuePointer Temp;
Temp=(QueuePointer)malloc(LEN);
if(Temp==NULL){
printf("开辟空间出错,入队失败!\n");
}
else{
Temp->Data=data;//数据域
Temp->Next=NULL;//指针域
(queue->Back)->Next=Temp;//连接
(queue->Back)=Temp;//更新
printf("%c元素入队成功!\n",(queue->Back)->Data);
}
}
4)出队---时时刻刻判断是否对空(对空标志是只剩下第一个结点)
//出队队头删除,时时刻刻判断是否为空,少用了一个结点的空间即头指针指向的结点
void Out_LinkQueue(LinkQueue* queue,ElementType* data){
QueuePointer Temp;
//如果链队为空
if((queue->Head)->Next==NULL){
queue->Back=queue->Head;
(queue->Back)->Next=NULL;
printf("链队为空,无法出队!\n");
}
else{
Temp=(queue->Head)->Next;
(queue->Head)->Next=Temp->Next;
*data=Temp->Data;
free(Temp);
printf("%c元素出队成功!\n",*data);
}
}
5)计算链队结点个数---包括头结点
//计算链队长度,包括头结点
int LinkQueue_Length(LinkQueue queue){
QueuePointer Temp;
int length=0;
Temp=queue.Head;
while(Temp!=NULL){
length++;
Temp=Temp->Next;
}
return length;
}
6)取队头元素---头指针所指的结点的下一个位置
//取队头元素,在头指针所指的结点的下一个位置
void Get_LinkQueue_Head(LinkQueue queue,ElementType* data){
if((queue.Head)->Next==NULL){
printf("链队已空,无法取出队头元素!\n");
}
else{
*data=(queue.Head)->Next->Data;
}
}
二、实践
链队初始化
3次入队并计算长度
4次出队并计算长度
再次3次入队并计算长度
取队头元素显示
销毁并计算长度
#include
#include
#define MaxSize 100
#define ElementType char//如果要修改数据类型,只需修改这里的宏定义,入队出队的打印,取对头元素,主函数scanf和printf
#define LEN sizeof(QueueNode)
//链队的一个结点
typedef struct QueueNode{
ElementType Data;
struct QueueNode*Next;
}QueueNode,*QueuePointer;
//链队的头指针尾指针,链队的头指针指向的结点数据域为空,也就是少用这个元素的空间
typedef struct{
QueuePointer Head;
QueuePointer Back;
}LinkQueue;
//初始化
void Init_LinkQueue(LinkQueue* queue){
queue->Head=queue->Back=(QueuePointer)malloc(LEN);
if(queue->Head==NULL){
printf("初始化链队失败!\n");
exit(0);
}
else{
(queue->Head)->Next=NULL;//头指针指向的结点的Next指向空
printf("初始化链队成功!\n");
}
}
//销毁,第一个结点也会被释放
void Destroy_LinkQueue(LinkQueue* queue){
QueuePointer Temp;
while(queue->Head!=NULL){
Temp=(queue->Head)->Next;
free(queue->Head);
queue->Head=Temp;
}
if(queue->Head==NULL) printf("\n链队销毁成功!\n");
}
//入队,队尾插入,初始化后第一次的入队并不会给第一个结点赋值数据域,而是开辟第二个结点并给其数据域赋值
void Enter_LinkQueue(LinkQueue* queue,ElementType data){
QueuePointer Temp;
Temp=(QueuePointer)malloc(LEN);
if(Temp==NULL){
printf("开辟空间出错,入队失败!\n");
}
else{
Temp->Data=data;//数据域
Temp->Next=NULL;//指针域
(queue->Back)->Next=Temp;//连接
(queue->Back)=Temp;//更新
printf("%c元素入队成功!\n",(queue->Back)->Data);///
}
}
//出队队头删除,时时刻刻判断是否为空,少用了一个结点的空间即头指针指向的结点
void Out_LinkQueue(LinkQueue* queue,ElementType* data){
QueuePointer Temp;
//如果链队为空
if((queue->Head)->Next==NULL){
queue->Back=queue->Head;
(queue->Back)->Next=NULL;
printf("链队为空,无法出队!\n");
}
else{
Temp=(queue->Head)->Next;
(queue->Head)->Next=Temp->Next;
*data=Temp->Data;
free(Temp);
printf("%c元素出队成功!\n",*data);///
}
}
//计算链队长度,包括头结点
int LinkQueue_Length(LinkQueue queue){
QueuePointer Temp;
int length=0;
Temp=queue.Head;
while(Temp!=NULL){
length++;
Temp=Temp->Next;
}
return length;
}
//取队头元素,在头指针所指的结点的下一个位置
void Get_LinkQueue_Head(LinkQueue queue,ElementType* data){
if((queue.Head)->Next==NULL){
printf("链队已空,无法取出队头元素!\n");
}
else{
*data=(queue.Head)->Next->Data;
}
}
int main(){
LinkQueue queue;
char data;
printf("提示:链队的第一个结点规定不用,但是链队结点个数有包括第一个结点!\n\n");
//初始化
Init_LinkQueue(&queue);
printf("\n");
//3次入队
Enter_LinkQueue(&queue,'a');
Enter_LinkQueue(&queue,'b');
Enter_LinkQueue(&queue,'c');
//计算长度
printf("\n包括第一个结点,链队结点有%d个\n",LinkQueue_Length(queue));
printf("\n");
//4次出队
Out_LinkQueue(&queue,&data);
Out_LinkQueue(&queue,&data);
Out_LinkQueue(&queue,&data);
Out_LinkQueue(&queue,&data);
//计算长度
printf("\n包括第一个结点,链队结点有%d个\n",LinkQueue_Length(queue));
printf("\n");
//再次入队
Enter_LinkQueue(&queue,'A');
Enter_LinkQueue(&queue,'B');
Enter_LinkQueue(&queue,'C');
//计算长度
printf("\n包括第一个结点,链队结点有%d个\n",LinkQueue_Length(queue));
//取队头元素
Get_LinkQueue_Head(queue,&data);
printf("\n");
printf("队头元素是%c\n",data);
//销毁
Destroy_LinkQueue(&queue);
//计算长度
printf("\n包括第一个结点,链队结点有%d个\n",LinkQueue_Length(queue));
return 0;
}