前言
用栈和队列实现回文数判断
代码及易错点说明
- 库函数调用及栈和队列相应结构体声明
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
typedef char DataType;
//队列数据元素结构
typedef struct node {
DataType info;
struct node *next;
} QueueData;
typedef struct queueRecord {
QueueData *front, *rear ;
} LINKQUEUE;
typedef struct queueRecord *PLinkQueue;
struct stack {
DataType element; //数据元素
struct stack *next; //指向下一个数据元素的指针
};
typedef struct stack *PtrToNode;
typedef PtrToNode Stack;
- 队列相关操作
PLinkQueue createEmptyQueue_link( ) {
//请在此处填写代码,完成相应功能
/*-------begin----------*/
PLinkQueue head;
head = (PLinkQueue)malloc(sizeof(struct queueRecord));
if(head==NULL) {
printf("create head node failed!");
return NULL;
}
head->front=NULL;
head->rear=NULL;
return head;
/*-------end----------*/
}
int isEmptyQueue_link(PLinkQueue queue) {
//请在此处填写代码,完成相应功能
/*-------begin----------*/
return queue->front==NULL;//为空返回1,不为空返回0
/*-------end----------*/
}
void enQueue_link(DataType x, PLinkQueue queue) {
//将数据元素x插入队尾。实质:生成一个struct node类型的结点,并给相应成员赋值后插入队尾
//请在此处填写代码,完成相应功能
/*-------begin----------*/
QueueData *s = (QueueData*)malloc(sizeof(struct node));
if(s==NULL){
printf("create a new node for queue failed!");
}
s->info=x;
s->next=NULL;
if(queue->front==NULL) {
queue->front=s;
} else{
queue->rear->next=s;
}
queue->rear=s;
/*-------end----------*/
}
DataType deQueue_link(PLinkQueue Q) {
//取出Q队列的队首结点,返回该结点的数据元素
//请在此处填写代码,完成相应功能
/*-------begin----------*/
if(!isEmptyQueue_link(Q)) {
QueueData *s;
s=Q->front;
DataType x=Q->front->info;
Q->front=s->next;
free(s);
return x;
}
/*-------end----------*/
}
注意点:
if(queue->front==NULL) { queue->front=s; } else{ queue->rear->next=s; } queue->rear=s;
入队当中的这一段代码,queue->rear=s;是无论传入队列属于哪种类型都应该进行的操作
- 栈的相关操作
int isEmpty(Stack s) {
return s->next==NULL;
}
/*
函数名:createStack
函数功能:创建一个空栈,实际上只需要初始化栈头结点
函数参数:无
返回值:栈头结点指针
*/
Stack createStack(void) {
Stack s ;
s =(PtrToNode)malloc(sizeof(struct stack));
if(s==NULL){
printf("create node for stackhead failed!");
return NULL;
}
s->next = NULL;//栈顶
return s;
}
/*
函数名:push
函数功能:向栈中压人一个数据元素值为x
函数参数:待压栈的数据元素,栈头结点指针
返回值:无
*/
void push(DataType x,Stack s) {
//表头作为栈顶
PtrToNode temp ;
temp=(PtrToNode)malloc(sizeof(struct stack));
if(temp==NULL){
printf("create node for new node failed!");
}
temp->element = x;
temp->next = s->next;
s->next = temp;
}
/*
函数名:pop
函数功能:弹出栈顶元素并返回元素值
函数参数:栈头结点指针
返回值:栈顶元素的值
*/
DataType pop(Stack s) {
PtrToNode temp;
DataType t;
if(!isEmpty(s)) {
temp = s->next;
t = temp->element;
s->next = temp->next;
free(temp);
return t;
}
else printf("stack is emtpty!");
}
DataType top(Stack s) {
if(isEmpty(s)==0) return s->next->element ;
else{
printf("nothing in top");
return NULL;
}
}
- 回文函数
int ishuiwen(DataType src[]) {
/*-------begin----------*/
//printf("输入的字符串为:");
//printf("%s",src);
PLinkQueue s = createEmptyQueue_link( );
//printf("succeed in create queue!");
Stack stack = createStack();
//printf("succeed in create stack!");
int i=0;
while(src[i]) {
enQueue_link(src[i],s);
//printf("第%d号元素入队成功!",i);
push(src[i],stack);
//printf("第%d号元素入栈成功!",i);
i++;
}
//printf("succeed in enqueue and push!");
int flag=1;
if(isEmptyQueue_link(s)){
flag=0;
printf("queue is empty!");
}
if(isEmpty(stack)){
flag=0;
printf("stack is empty!");
}
while((!isEmptyQueue_link(s))&&(!isEmpty(stack))){
if(pop(stack)!=deQueue_link(s)) {
// printf("%c",pop(stack));
// printf("%c",deQueue_link(s));
// printf("该元素不符合!");
flag=0;
break;
}
}
if(flag==1) {
return 1;
} else {
return 0;
}
}
- 主函数
int main(void) {
DataType str[20];
scanf("%s",str);
if(ishuiwen(str)) {
printf("yes");
} else {
printf("no");
}
return 0;
}
最后再提醒一下:我记得原来的兄台写的代码栈和队列的元素类型定义不一致,一个是char,另一个是int,我有种大胆的猜测,ta应该是将再之前栈相关的闯关代码直接copy到这里来而没有修改数据类型,所以最初匹配失败。所以还是建议小伙伴们考虑栈和队列的结构都使用同一个,再typedef不同的名字,避免混淆。
另外,虽然当代码量较大程序较复杂时时用全局变量可能有害,但对于这种解决的是同一组数据的问题,用typedef将DataType确定下来是很有帮助的,0和‘0’毕竟真的不一样不是吗?
结语
不要直接copy人家的代码!不要直接copy人家的代码!不要直接copy人家的代码!重要的事情说三遍!
我花了两个多小时排错的泪,都是当初敷衍作业的时候脑子进的水!
学期末老师开启了查重功能,我和n个八竿子打不着的同学代码百分之百重合,想想真是天雷滚滚……估计是大家都打开了同一个搜索引擎、找到了同一个页面吧……
这不是重点,重点是老师给了一次机会,说想证明自己不是抄袭的同学要带上源代码现场改功能,能改出来说明真的会了、也不是简单复制粘贴的。
于是问题来了,我打开了这段几个月前忘了从哪里找来的代码,一在本地运行、发现无法满足测试样例,估计也只是侥幸过了评测平台的测试吧?
于是我开始修改这段代码,从只是无法输出正确结果到出现更大的问题、再到将问题逐一排查并解决,我用了两个多小时,害,早知今日何必当初呢?要是自己从头到尾写一遍估计不需要一个小时吧?
这位兄台写的代码本身和我的代码习惯并不一致,很多地方的处理方式都不同,我排查起来真的很头痛!(当然各位现在看到的除了变量名之外已经基本被我魔改过了)
不过也有很多经验教训和收获,比如:不要抄作业,要借鉴人家的思路,然后自己动手丰衣足食;再比如,其实在这个排查的过程中也是更深入地理解了一些原理和细节,人没得点教训是不长记性的,什么问题都不出光看看还真就以为自己全懂了……排查自己的代码错误也是同理。
希望到时候再次魔改代码顺顺利利!