队列实现回文判断

数据结构实验

  • 能实现队列的顺序存储和链式存储下的基本操作

实验内容

  • 有一类字符串,将其所有字符倒过来后和原来一样,这种字符串被称为“回文”。如121、abcba都是回文,abA、abad都不是回文。请你使用队列的基本操作设计程序,运行后可以接受用户输入一个不超过10个字符的字符串,并通过你的程序判断该是否是回文,是则输出yes,否则输出no。

实验过程

设计思路

  • 因为要实现队列的顺序存储和链式存储两个基本操作,用队列解决“比较回文”,直接使用两种方式将输入字符串进行存储,由于队列的是一边进一边出,所以判断回文时,使两队列在同一个循环中,顺序存储队列顺序输出和链式存储队列顺序输出(这里的链式存储在将字符串存储后经过逆序处理),两队列值相比是否相等,返回相应判断的bool值,根据判断输出结果。

代码实现解释

  • 定义队列链式存储的节点结构,即存储内容和下一个节点的地址;定义一个类似于head作用的指针节点,这个节点存放front指针和rear指针,其中front、rear指针就是指向链式存储队列地址的指针;定义一个head的指针PLinkQueue,定义队列顺序存储的节点结构。
  • 创建一个空link队列。生成head管理节点,并初始化front和rear,一开始队列为空,front和rear指向同一处。
  • 判断link队列是否为空。即判断front指针是否为空,若为空,返回0;若不为空,返回1。
  • 将数据元素X插入队尾。生成一个队列节点,将数据元素X存入节点,再将节点入队,这里注意先判断队列是否为空,即front=NULL,如果是,则插入元素的地址即为队列的首地址front;如果不为空,就将节点插入队尾,尾插法,插入后,队尾指针往后移,返回一个bool值,用于测试时判断是否插入成功。
  • 队列逆置。这里采用的是带头结点的链表逆置方法,由于我们的队列没有头节点,所以用一个temp暂时代替,然后将pu->front指向temp,使用两个s,p移动指针,一个用于处理当前节点的移动,另一个存放队列未逆置的元素,其移动过程有点像一个固定高度的环节点,中间穿过一根左右两端打结的绳子,本来绳的左端在环节点处(原队头),现在从绳的左端拉下去,右端就上来(原来的队尾,现在的队头),从而实现链式队列的逆置。
  • 出队。取出队列的首节点,front后移,并释放该节点,返回该节点元素。
  • 函数isEmpty(),用于判断顺序队列是否为空,即判断front==rear,返回判断的bool值。
  • 顺序队列的初始化。初始化顺序队列的head指针sq,给队头队尾赋值,返回sq。
  • 队列入队。这里的字符串长度有限,所以不需要判断顺换队列是否满队,直接入队就好。
  • 出队。判断队列是否为空,非空,在对头出队,front后移,返回出队元素。
  • 回文判断。使两队列在同一个循环中,顺序存储队列顺序输出和链式存储队列顺序输出(这里的链式存储在将字符串存储后经过逆序处理),两队列值相比是否相等,返回相应判断的bool值。
    主函数实现字符串输入,回文函数isPalindrome(str)的调用,根据返回的bool值输出结果。

代码实现


//能实现队列的顺序存储和链式存储  判断回文

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXNUM 20

typedef char DataType;	//定义数据变量 

//链式存储 队列、栈的 数据元素结构
typedef struct node
{
	DataType info;
	struct node *next; 
}QueueData;

//队的指针,相当于head   
typedef struct queueRecord		// 对头、队尾指针  连两个指向同一队列的不同指针 
{
	QueueData *front, *rear;
}LinkQueue;


//顺序存储 
typedef struct queue
{
	int front;
	int rear;
	DataType *element;
}SeqQueue;

typedef struct queueRecord *PLinkQueue;
typedef struct queue *Queue;


//创建一个空队列,生成一个LinkQueue类型的节点。并初始化成员front和rear
PLinkQueue createEmptyQueue_link()
{
	PLinkQueue list = (PLinkQueue )malloc(sizeof(struct queueRecord)); 
	if(list!=NULL)
	{
		list->front=NULL;
		list->rear=NULL;
		return list;
	}
	return NULL;
}


//判定队列是否为空,看队列的front指针是否为空,若为空,则队列为空,返回0,若不为空,返回1 
int isEmptyQueue_link(PLinkQueue qu)
{
	if(qu->front!=NULL)	return 1;
	return 0;
} 


//将数据元素X插入队尾,生成一个struct node类型的节点,并给相应的成员赋值后插入队尾
int inQueue_link(DataType x, PLinkQueue qu)
{
	QueueData *data=(QueueData *)malloc(sizeof(struct node));   // 给插入元素初始化节点
	if(data==NULL) return 0;
	
	data->info=x;
	data->next=NULL;
	
	if(qu->front==NULL)
	{
		qu->front=data;	//当开始没有元素时,插入元素的首地址即为队头p
		qu->rear=data; 
	} 
	else
	{
		qu->rear->next=data;  //尾插法,插入后,队尾指针往后移,即插入元素的地址 
		qu->rear=data;
	}
	return 1;
} 
 

//队列逆置,不用考虑队尾指针 
void queueRevers(PLinkQueue pu)
{
	QueueData *p, *s;
	QueueData *temp=(QueueData *)malloc(sizeof(struct node));
	temp->info=1;
	temp->next=pu->front;
	
	pu->front=temp;
	
	p=pu->front->next;
	pu->front->next=NULL;
	
	while(p)
	{
		s=p;
		p=p->next;
		s->next=pu->front->next;
		pu->front->next=s;
	}
	
	pu->front=pu->front->next;
	free(temp);
}


//出队,取出qu队列的首节点,并释放该节点 ,返回该节点的元素
DataType delQueue_link(PLinkQueue pu)
{
	QueueData *p;
	int temp=pu->front->info;
	p=pu->front;					//取出元素后释放该节点 
	pu->front=pu->front->next;
	free(p);
	return temp;
} 


 //下面放之前写过的栈的代码

int isEmpty(Queue sq) 		// 这里先判断,有点奇怪,如果先创建结构体,节点内容是默认的
{							 
	if(sq->rear==sq->front) return 1;
	return 0;
}

//顺序队列初始化
Queue createSeqQueue() 
{
	Queue sq=(Queue )malloc(sizeof(struct queue));
	if(sq==NULL) return NULL;
	
	sq->element=(DataType *)malloc(sizeof(struct queue)*MAXNUM);
	if(sq->element==NULL) return NULL;
	
	sq->front=sq->rear=0;
	return sq;
}


//有限的队列入队可以这样 
int pushSeqQueue(DataType x, Queue sq)
{
	sq->element[sq->rear]=x; 
	sq->rear=(sq->rear+1)%MAXNUM; 
	return 1;
}


//出队列
DataType popQueue(Queue sq)
{
	DataType temp;
	if(!isEmpty(sq))  //队列非空
	{
		temp=sq->element[sq->front];
		sq->front=(sq->front+1)%MAXNUM;
	}
	return temp;
} 


//回文判断 
int isPalindrome(char str[])
{
	int flag;
	int j=0;
	PLinkQueue pu=createEmptyQueue_link();
//	printf("%d", pu); 							initialize successful
	char t1, t2;
	Queue sq=createSeqQueue();
//	printf("%d", s);
	
	for(int i=0; i<strlen(str); i++)
	{
		flag=inQueue_link(str[i], pu);
//		printf("qu %d\n", flag);
		flag=pushSeqQueue(str[i], sq);
//		printf("sta %d\n", flag);
	}
	j=strlen(str)-1;
	
    queueRevers(pu);
	for(int i=0; i<strlen(str); i++, j--)
	{
//		printf("%c\n", popQueue(s));
		t1=delQueue_link(pu);
//		printf("\n%c ", t1);
		t2=popQueue(sq);
//		printf("%c\n", t2);	
		if(t1!=t2) return 0;
	}
	return 1;
}

int main(void)
{
	char str[20];   // 输入一个不超过10个字符的字符串 
	int flag=0;
	
	scanf("%s", str);
	flag = isPalindrome(str);
	if(flag) printf("yes!");
	else printf("no!");
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值