判断是否为回文字符串(栈、队列、链表、快慢指针)

假设正读和反读都相同的字符序列为“回文字符串”,例如,"abba"和"abcba"是回文字符串,“abcde” 和"ababab"则不是回文字符串。试写一个程序判断输入的字符串是否为回文字符串。

方法一:
1.将字符串按照用户输入的顺序分别入栈和队列
2.分别从队列和栈中取出首个字符
3.比较取出的字符,若相等,继续分别从队列和栈中取首个字符;
否则跳出循环,并设置标志 flag=0;
4.若队列和栈中的字符取完,则结束,设置标志flag=1;
5.flag=1,表示字符从前往后和从后往前的序列完全匹配,该字符串属于回文
6.flag=0,表示字符从前往后和从后往前的序列不完全匹配,该字符串不属于回文

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

#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10

typedef char ElemType;
typedef struct strStack
{
	ElemType *base;
	ElemType *top;
	int StackSize;
} sqStack;//定义一个栈
struct strQueue
{
	ElemType e;
	struct strQueue *next;
};
typedef struct Queue
{
	struct strQueue *front;
	struct strQueue *rear;
} Queue;//定义一个队列

void InitStack(sqStack *S);//初始化栈
void Push_Stack(sqStack *S, ElemType e);//入栈
void Pop(sqStack *S, ElemType *e);//出栈
void InitQueue(Queue *Q);//初始化队列
void InserQueue(Queue *Q, ElemType e);//入队列
void DeleteQueue(Queue *Q, ElemType *e);//出队列
int StackLen(sqStack S);//求栈的长度
int main()
{
	sqStack S;
	Queue Q;
	InitStack(&S);
	InitQueue(&Q);//初始化栈和队列
	char ch;
	int len;//栈的长度
	int flag = 1;
	/*将所有元素入栈、入队列*/
	while((ch = getchar()) != '\n')
	{
		Push_Stack(&S, ch);
		InserQueue(&Q, ch);
	}
	len = StackLen(S);//栈的长度
	for(int i = 0; i < len; i++)
	{
		char elem_stack, elem_Queue;
		Pop(&S, &elem_stack);
		DeleteQueue(&Q, &elem_Queue);
		/*依次出栈、出队列*/
		/*当取出的元素不一样时,则已经不是回文串,跳出循环*/
		if(elem_stack != elem_Queue)
		{
			flag = 0;
			break;
		}

	}
	if(flag == 0)
	{
		printf("不是回文串\n");
	}
	else
	{
		printf("是回文串\n");
	}
	return 0;
}
void InitStack(sqStack *S)//初始化栈
{
	S->base  = (ElemType*)malloc(STACK_INIT_SIZE * sizeof(ElemType));
	if(S->base == NULL)
	{
		exit(-1);
	}
	S->top = S->base;
	S->StackSize = STACKINCREMENT;
}

void Push_Stack(sqStack *S, ElemType e)//入栈
{
	if(S->top - S->base == S->StackSize)
	{
		S->base = (ElemType*)realloc(S->base, (STACKINCREMENT + S->StackSize) * sizeof(ElemType));
		if(S->base == NULL)
		{
			exit(-1);
		}
	}
	*(S->top) = e;
	S->top ++;
}

void Pop(sqStack *S, ElemType *e)//出栈
{
	if(S -> top == S->base)
	{
		return ;
	}
	*e = *--(S->top);
}

void InitQueue(Queue *Q)//初始化队列
{
	Q->front  = Q->rear = (struct strQueue*)malloc(sizeof(struct strQueue));
	if(!Q->front)
	{
		exit(0);
	}
	else
	{
		Q->front->next = NULL;
	}
}

void InserQueue(Queue *Q, ElemType e)//入队列
{
	struct strQueue *q = (struct strQueue*)malloc(sizeof(struct strQueue));
	if(!q)
	{
		exit(-1);
	}
	else
	{
		q->e = e;
		q->next = NULL;
		Q->rear->next = q;
		Q->rear = q;
	}
}

void DeleteQueue(Queue *Q, ElemType *e)//出队列
{
	if(Q->front == Q->rear)
	{
		return ;
	}
	else
	{
		struct strQueue *q = Q->front->next;
		*e = q->e;
		Q->front->next = q->next;
		if(Q->rear == q)
		{
			Q->rear = Q->front;
		}
		free(q);
	}
}
int StackLen(sqStack S)//求栈的长度
{
	return (S.top  -  S.base);
}

方法二:
1、将字符存入一个双向循环链表
2、从表头往后和表尾往前分别取一个元素,若不相等,则设置flag = 0,并跳出循环;
3、若元素全部取完,则设置flag = 1;
4、flag=1,表示字符从前往后和从后往前的序列完全匹配,该字符串属于回文
5、flag=0,表示字符从前往后和从后往前的序列不完全匹配,该字符串不属于回文

#include <stdio.h>
#include <stdlib.h>
typedef char ElemType;
//定义一个双向循环链表
typedef struct DualNode
{
	ElemType data;
	struct DualNode *prior;
	struct DualNode *next;
} DualNode, *DuLinkList;
void Init_DuLinkList(DuLinkList *L);//初始化双向循环链表
void InsertDulinkList(DuLinkList *L, ElemType e);//插入元素
int main()
{
	DuLinkList L;
	Init_DuLinkList(&L);
	char ch;
	int flag = 1;
	while((ch = getchar())  != '\n')
	{
		InsertDulinkList(&L, ch);
	}//依次插入
	DuLinkList head, tail;
	head = L->next;//head指向第一个有元素的节点
	tail = L->prior;//tail指向最后一个有元素的节点
	while(head != tail)
	{/*tail与head相等时结束循环,当元素个数为奇数时则每个指针只需走一半即可
	元素个数为偶数时,每个指针都需要移动一圈走到头结点*/
		if(head->data != tail->data)
		{
			flag = 0;
			break;
		}
		head = head->next;
		tail = tail->prior;
	}
	if(flag == 1)
	{
		printf("是回文串\n");
	}
	else
	{
		printf("不是回文串\n");
	}
	return 0;
}

void Init_DuLinkList(DuLinkList *L)//初始化双向循环链表
{
	*L = (DuLinkList)malloc(sizeof(DualNode));//分配一个空间
	if(!(*L))
	{
		exit(0);
	}
	else
	{
		(*L)->next = (*L);
		(*L)->prior = (*L);
	}
	/*头结点data域没有数据*/
}
void InsertDulinkList(DuLinkList *L, ElemType e)
{
	DuLinkList new = (DuLinkList)malloc(sizeof(DualNode));
	DuLinkList p = (*L)->prior;//p为头结点前的节点,相当于尾结点
	new->data = e;
	new->next = *L;//新节点的next指向头结点
	new->prior = p;//新节点的prior域指向原“尾节点”
	p->next = new;//原“尾结点”的next域指向新节点
	(*L)->prior = new;//把头结点的prior域指向新节点
	/*此部分代码画图理解更佳,此不赘述*/
}

方法三:
1、利用快慢指针把单链表前半部分逆转并把链表分成两个链表。
2、依次比较两个单链表节点的data域,出现不相同的地方,则必不为回文字符串,若两个链表走到了最后,退出循环,则为回文串

#include <stdio.h>
#include <stdlib.h>
typedef char ElemType;
typedef struct LNode
{
	ElemType data;
	struct LNode *next;
} LinkNode, *LinkList;
void InitList(LinkList *L, int n);
LinkList Div_ReverseList(LinkList *L);
void Compare(LinkList former,LinkList latter);
int main()
{
	LinkList L = NULL;
	int n;
	printf("输入字符个数\n");
	scanf("%d", &n);
	fflush(stdin);
	InitList(&L, n);
	LinkList former = Div_ReverseList(&L);
	LinkList latter = L;
	Compare(former,latter);
	return 0;
}
void InitList(LinkList *L, int n)
{
	printf("请输入含%d个字符的字符串\n",n);
	char c;
	*L = (LinkList)malloc(sizeof(LinkNode));
	(*L)->next = NULL;
	scanf("%c", &c);
	(*L)->data = c;
	LinkList q  = *L;
	LinkList p;
	for(int i = 0; i < n - 1; i++)
	{
		p = (LinkList)malloc(sizeof(LinkNode));
		scanf("%c", &c);
		p->data = c;
		q->next = p;
		q = p;
	}
	p->next = NULL;
}

LinkList Div_ReverseList(LinkList *L)//将链表逆转一半分成两个等长链表
{
	LinkList lslow = *L;//慢指针
	LinkList lfast = (*L)->next;//快指针
	LinkList temp = NULL;
	if(lslow->next == NULL)//只有一个节点,返回头结点
	{
		return lslow;
	}
	while(lslow->next != NULL&&lfast->next != NULL && lfast->next->next != NULL)
	{
		*L = lslow->next;
		lslow->next = temp;
		temp = lslow;
		lslow = *L;
		lfast = lfast->next->next;
	}
	if(lfast->next == NULL)
	{
		*L = lslow->next;
		lslow->next = temp;
		return lslow;
	}//此时,链表分成了以lslow和*L为头结点的两个单链表
	else //(lfast->next->next == NULL)
	{
		LinkList t = (*L)->next;
		*L = lslow->next->next;
		lslow->next = temp;
		free(t);//把中间的节点释放掉
		return lslow;
	}//此时链表分成了以temp和*L为头结点的两个链表
}
void Compare(LinkList former,LinkList latter)
{
	while(former != NULL)
	{
		if(former->data != latter->data)//出现一处不相等,就必不是回文串
		{
			printf("No\n");
			break;
		}
		former = former->next;
		latter = latter->next;
	}
	if(former == NULL)//走到最后
	{
		printf("YES\n");
	}
}


  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值