用链表实现回文判断

本文聚焦用链表实现回文判断。介绍了朴素的遍历字符串数组实现方式后,重点阐述链表实现。包括链表建立、插入,字符串转链表的尾插法,以及链表回文判断算法。最后指出因结构体用char,程序仅支持英文和数字,处理中文需修改。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

用链表实现回文判断

判断回文是一个非常经典的算法,其朴素实现也非常容易,如下第一段代码,用遍历字符串数组的方式实现,但本文讨论重点的是用链表实现。

//回文判断(字符数组) 
#include<stdio.h>
#include<cstring>
int main(){
	int len;
	char str[50];
	gets(str);
	len=strlen(str);
	for(int i=0;i<len/2;i++){
		if(str[i]!=str[len-i-1]){
			printf("不是回文");
			return 0; 
		}
	}
	printf("回文");
	return 0;
}

链表实现的完整代码如下:

//用链表实现回文判断 
#include<stdio.h>
#include<stdlib.h>

typedef struct node{
	char data;
	node *next;
}*LinkList,*pNode;

int len;	//该变量用于存放字符串长度 即链表长度 
int DIYstrlen(char *p){	//获取字符串长度
	int n=0;
	while(*p++)
		n++;
	return n;
}

LinkList GetEmptyList(){	//初始化链表 
	LinkList head = (pNode)malloc(sizeof(pNode));
	head->data=0;
	head->next=NULL;
	return head;
}
//字符串到链表
LinkList String2LinkList(char str[]){
	LinkList L = GetEmptyList();
	len = DIYstrlen(str);
	//printf("字符串长度为:%d\n",len); 
	int i=0;
	pNode p = L;
	while(str[i]){
		p->next = (pNode)malloc(sizeof(pNode));
		p->next->data=str[i++];
		p=p->next;
	}
	p->next=NULL;
	return L;
} 
//显示链表内容 
void show(LinkList L){
	pNode p = L->next;
	while(p){
		printf("%c ",p->data);
		p=p->next;
	}
	printf("\n");
}

//判断回文算法 
void isPalindromic(LinkList L){
	int i,n=len;//len为链表长度 
	char s[n/2];
	pNode p=L->next;
	for(i=0;i<n/2;i++){
		s[i]=p->data;
		p=p->next;
	}
	i--;	//i多加1  需要减回来 
	if(n%2==1)	//若链表长为奇数 中间的字符不需处理 直接跳过 
		p=p->next;
	while(p!=NULL&&s[i--]==p->data){
		p=p->next;
	}
	if(i==-1)
		printf("该字符串是回文");
	else 
		printf("该字符串不是回文");
} 

int main(){
	char s[100];
	printf("输入字符串:\n");
	gets(s);
	printf("链表的内容为:\n");
	LinkList L = String2LinkList(s);
	show(L);
	isPalindromic(L);
	return 0;	
}

部分代码参考自:点击此处

本程序有以下几个难点,笔者逐一解析:
1.结构体的使用,链表的建立和插入
2.字符串转为链表

字符串转为链表
转换思想:先获取字符串长度,逐个遍历字符串,采用尾插法逐个字符插入链表,读到’\0’即结束(注:’\0’的ASCII码为0,’\0’和0等效)

//字符串到链表
LinkList String2LinkList(char str[]){
	LinkList L = GetEmptyList();
	len = DIYstrlen(str);
	//printf("字符串长度为:%d\n",len); 
	int i=0;
	pNode p = L;
	while(str[i]){
		p->next = (pNode)malloc(sizeof(pNode));
		p->next->data=str[i++];
		p=p->next;
	}
	p->next=NULL;
	return L;
} 

判断回文(链表):
算法思想:将链表的前一半存入数组,链表继续往下走,此时逆序遍历数组,逐个对比,用i作为数组的下标,如遍历完之后退出循环,此时i的值小于0(即为-1),i==-1即为回文,其余值则不为回文

void isPalindromic(LinkList L){
	int i,n=len;//len为链表长度 
	char s[n/2];
	pNode p=L->next;
	for(i=0;i<n/2;i++){
		s[i]=p->data;
		p=p->next;
	}
	i--;	//i多加1  需要减回来 
	if(n%2==1)	//若链表长为奇数 中间的字符不需处理 直接跳过 
		p=p->next;
	while(p!=NULL&&s[i--]==p->data){
		p=p->next;
	}
	if(i==-1)
		printf("该字符串是回文");
	else 
		printf("该字符串不是回文");
} 

最后附上效果图:

在这里插入图片描述
在这里插入图片描述
注意在结构体只定义了char,char只支持1个字符,中文的存储需要用2个字符,故会产生如下错误,第二个的程序只支持处理英文和数字字符,如需处理中文需要稍作修改。
在这里插入图片描述
在这里插入图片描述

判断一个链表是否为回文可以借助快慢指针将链表分为两部分,同时需要反转其中一部分再逐一比较两个部分的值。下面是具体的步骤以及完整的C语言实现代码: ### 步骤说明 1. **找到链表的中点**:通过快慢指针法确定链表的中间节点。 2. **反转后半部分链表**:从中间节点开始反转后面的链表。 3. **对比前后两部分**:分别从前到后遍历原链表的第一部分和反转后的第二部分,检查对应的节点值是否相等。 4. **恢复链表(可选)**:为了保证原始链表结构不变,可以再次反转链表的后半部分。 以下是基于以上思路的完整C语言实现代码: ```c #include <stdio.h> #include <stdlib.h> typedef struct Node { int data; struct Node* next; } Node; // 创建新结点并赋初值 Node* create_node(int val) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = val; newNode->next = NULL; return newNode; } // 插入结点到链表末尾 void append_node(Node** head_ref, int new_data) { Node* newNode = create_node(new_data); if (*head_ref == NULL) { *head_ref = newNode; return; } Node* last = *head_ref; while(last->next != NULL) last = last->next; last->next = newNode; } // 反转链表辅助函数 Node* reverse_list(Node* head){ Node* prev = NULL; Node* current = head; Node* next = NULL; while(current != NULL){ next = current->next; current->next = prev; prev = current; current = next; } return prev; } int is_palindrome(Node* head){ if(head == NULL || head->next == NULL) return 1; // 单个节点或空链表视为回文 Node* slow = head; Node* fast = head; // 找到中间节点(slow最终会停在中间) while(fast != NULL && fast->next != NULL){ slow = slow->next; fast = fast->next->next; } // 如果fast非空则链表长度为奇数,跳过中心元素 if(fast != NULL) slow = slow->next; // 翻转后半部分链表 Node* second_half_start = reverse_list(slow); // 判断前半部分和翻转后的后半部分是否一致 Node* p1 = head; Node* p2 = second_half_start; while(p2 != NULL){ if(p1->data != p2->data) return 0; // 发现不同即不是回文 p1 = p1->next; p2 = p2->next; } // 恢复链表(选择性操作),如果不关心原始链表结构这一步可以省略 reverse_list(second_half_start); return 1; // 链表回文 } // 主函数演示如何使用上面定义的功能 int main(){ Node* head = NULL; append_node(&head, 1); append_node(&head, 2); append_node(&head, 3); append_node(&head, 2); append_node(&head, 1); printf("Is palindrome: %s\n", is_palindrome(head)? "Yes" : "No"); return 0; } ``` 此示例首先建立了一个带有整数值的单向链接串列,并添加了一些节点形成潜在的回文序列。接着实现了is_palindrome 函数来检测这个链表是不是回文形式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值