数据结构基本操作_数据结构(C语言)-链队列基本操作

本文介绍了链队列这一数据结构,包括其先进先出的特性、不同类型的队列以及链队列的实现方式。通过C语言代码展示了链队列的初始化、入队、出队和销毁等基本操作,特别强调了在链队列中添加头结点以简化操作。同时,文章提供了包含学生学号的链队列示例,注重用户交互和视觉效果。最后,鼓励读者对代码进行讨论和补充。
摘要由CSDN通过智能技术生成

6d5f3e6f8a1bc37cbfaf648a1374734d.png

导语

队列是一种先进先出(first in first out,FIFO)的线性表,是一种常用的数据结构。

它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时,称为空队列。

f86891d0add5d6715c00ff0aeace95b5.png
图1 队列

队列有很多种,按照存储结构划分,有链式队列,循环队列,单向队列,双端队列

实现队列的方式也有很多种,如基于链式存储结构的链接队列(又称链队列),基于顺序存储结构的队列

本文介绍链队列的实现和一些基本操作,并用代码的形式讲解

一些概念

  1. 一个链队列需要两个指针才能唯一确定,它们分别指示队头和队尾(分别称为头指针和尾指针)
  2. 与线性表的单链表一样,为了操作方便起见, 给链队列添加一个头结点,并令头指针指向头结点
  3. 空的链队列的判别条件为头指针和尾指针均指向头结点

8cc1fe308fcb229ef0527ecc503140fa.png
图2 队列的链式存储结构(链队列)

链队列的操作

以下代码实现了一个可以保存学生学号(最长12位的字符串)链队列,实现了它的初始化,出队,入队,队列销毁的操作:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define OK 1
#define NO 0
//OK和NO是自定义的状态变量

//链队列结点
typedef struct Qnode{
	char* data;//数据域
	struct Qnode *next;//指针域,指向下一个结点
}Qnode;

//链队列
typedef struct{
	Qnode* front;//队头指针 相当于Qnode *front 
	Qnode* rear;//队尾指针	
}LinkQueue;

	
//初始化队列函数
int initQueue(LinkQueue* Q){
	//给头尾结点分配内存,让队列中头尾指针指向同一个内存 
	Q->front  = (Qnode*)malloc(sizeof(Qnode));
	Q->rear = Q->front;
        //储存分配失败 
	if(!Q->front)return NO;
        //成功
	Q->front->next = NULL;
	return OK;
}

//插入元素,成为新的队尾元素
int insertQueue(LinkQueue* Q){

	
	Qnode* tempNode;//声明一个临时结点

	char *stuId = (char*)malloc(sizeof(12));//声明变量来接收如数
	
	tempNode = (Qnode*)malloc(sizeof(Qnode));
        //如果内存分配失败
	if(!tempNode)	return NO;

	//输入学号并保存			
	scanf("%s",stuId); 	
	tempNode->data = stuId;
	tempNode->next = NULL;
	Q->rear->next = tempNode;
	Q->rear = tempNode;		
	return OK;
}

//元素出队
char* outQueue(LinkQueue* Q){
	//若队列为空
	if(Q->front==Q->rear) {
		return NULL;  
	}
	//若队列不空,则让队列头部元素出队 
	Qnode* p = Q->front->next;
	char* data_return = p->data;
	Q->front->next = p->next; 
	//如果只有一个元素,该元素出队后,就让尾指针和头指针指向相同,相当于重置链队列
	if(Q->rear==p) Q->rear = Q->front; 
	//如果不止一个元素,就不用重置尾指针位置 
	
	free(p);
	return data_return;
} 

//销毁队列
int destroyQueue(LinkQueue* Q){
	while(Q->front){
		Q->rear = Q->front->next;
		free(Q->front);
		Q->front = Q->rear;
	}
	return OK;
}

//返回队列长度,用于计算还剩多少个元素结点在队列里
int queueLenth(LinkQueue* Q){
	Qnode* p =Q->front->next;
	int count=0;
	while(p){
		count++;
		p = p->next;
	}
	return count;
} 

//主函数
int main(){
	
	// 初始化队列 	
	LinkQueue Q;

	//定义一个表示选择的变量 
	int choice;
	
	//元素插入个数 
	int num; 
	
	//出队返回值
	char* back; 
	do{	
		printf("==========链队列操作===========n");
		printf("1.初始化链队列n");
		printf("2.元素入队n");
		printf("3.元素出队n");
		printf("4.销毁队列n");
		printf("0.退出n");
		printf("=====================n");
		printf("请输入您的选择:");
		scanf("%d",&choice);
			switch(choice){
				case 1:
					initQueue(&Q)?printf("------------n -->> 链队列初始化成功n------------n"):printf("------------n -->> 链队列初始化失败n------------n");
					break;
				case 2:
					
				printf("请输入插入元素个数:");
				scanf("%d",&num);
				int i;
    			for(i=0;i<num;i++){	
					printf(" 请输入第%d个学生的学号:",i+1);			  								      
					if(!insertQueue(&Q))printf("------------n-->> 第%d元素入队失败n",i+1);
				} 
				
					break;
				case 3:
					back = outQueue(&Q);
					back? printf("------------n 元素: %s 出队,还剩%d个元素n",back,queueLenth(&Q)):printf("------------n队列为空,无法出队!n"); ; 			
					break;
				case 4:
					destroyQueue(&Q)?printf("------------n队列销毁成功!n"):printf("------------n队列销毁失败!n");
					break;
				case 0:
					printf("n-->> 退出n"); 
					exit(0);
					break;	
				default:
				 break; 
			}
	}while(choice);
	
	
}

主函数里主要是考虑到用户交互和视觉效果,所以有很多printf函数用来打分割符。

以上代码经过调试,我自认为没有问题(鄙人才疏学浅)。如果读者朋友们,有疑问和更正,欢迎评论区补充和探讨

点击此处,可了解循环队列(基于顺序存储结构)的相关知识

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值