R6-1 回文字符串的判别(链栈)【可本地编译器调试】

本题要求设计一个算法,判断用户输入的字符串是否是回文字符串,用户输入的字符串同时存储于链栈和链队列中。

个人学习答案:

int JudgePalindrome(LinkStack st, LinkQueue qu)
{
    DataType a, b;
    while (!LinkQueueEmpty(qu))// 循环直到栈和队列都为空
    {
        Pop(st, &a);// 从栈中弹出数据
        DeLinkQueue(&qu, &b);//从队列中弹出数据
        //注意queue中linkqueue定义的不是指针!传入需要&
        if (a != b)// 比较弹出的数据
        {
            return -1;// 如果数据不一致,返回-1
        }
    }
    return 2; // 如果所有数据都一致,返回2
}

1. 为何要使用链栈和链队列,而不使用顺序栈和顺序队列?后者在本题场景下针对输入有什么局限性?
链栈和链队列的优势在于它们的空间动态分配。对于顺序栈和顺序队列,它们通常需要预先定义一个固定大小的数组来存储元素。如果输入的字符串长度超过了这个预定义的大小,那么顺序栈和顺序队列就无法处理这么多的元素,除非重新分配更大的空间,这可能会导致性能问题和内存浪费。而链栈和链队列可以根据需要动态地分配空间,因此它们可以处理任意长度的字符串,而不会受到预先定义的大小的限制。
2. 循环条件可以改成判栈空不?
循环条件可以改成判断栈是否为空。在上述代码中,我们是通过判断链队列是否为空来控制循环的,这是因为队列是先进先出的数据结构,它反映了原始字符串的顺序。但是,由于栈和队列的长度应该是相同的(因为它们存储的是同一个字符串),所以理论上也可以通过判断栈是否为空来控制循环。但是,由于我们在比较之前已经将链栈中的所有元素转移到了辅助栈中,因此实际上我们应该判断辅助栈是否为空。
3. 还有没有时间和空间上更高效的算法?(在本算法基础上优化改进)
在本算法的基础上,可以做一些优化来提高效率。一种方法是避免使用辅助栈,直接使用链栈进行比较。由于链栈的后进先出的特性,链栈的中间元素不容易直接访问。但是,我们可以同时从链栈的顶部和底部进行比较,这样就可以在不使用额外空间的情况下判断字符串是否为回文。这需要两个指针,一个指向栈顶,另一个指向栈底,然后同时向中间移动,比较对应的元素。

如:

int JudgePalindrome(LinkStack st, LinkQueue qu) {
    LinkStack slow = st->next, fast = st->next; // 慢指针和快指针初始化为栈顶
    SNode *prev = st; // 用于记录慢指针的前一个节点
    DataType stackTop, queueFront;
    // 使用快慢指针找到链栈的中点
    while (fast != NULL && fast->next != NULL) {
        prev = slow; // 更新前一个节点
        slow = slow->next; // 慢指针前进一步
        fast = fast->next->next; // 快指针前进两步
    }
    // 如果快指针没有达到链栈的末尾,说明链栈长度为奇数,慢指针需要再前进一步
    if (fast != NULL) {
        prev = slow; // 更新前一个节点
        slow = slow->next;
    }
    // 此时,慢指针指向链栈的中间位置,prev指向慢指针的前一个节点
    // 从链栈的中间位置开始,同时从顶部和底部比较元素
    while (slow != NULL) {
        Pop(st, &stackTop);
        DeLinkQueue(&qu, &queueFront);
        if (stackTop != queueFront) {
            return -1; // 发现不匹配的字符,返回-1
        }
        prev->next = NULL; // 断开链栈的上半部分
        free(slow); // 释放下半部分的节点
        slow = st->next; // 指向链栈的新底部
    }
    return 2; // 所有字符都匹配,是回文字符串
}

所涉及的链栈结点和链队列结点定义如下:

typedef char DataType;
/* 链栈的结点定义 */
typedef struct SNode
{  
    DataType data;            
    struct SNode *next;        
}SNode,*LinkStack;            
/* 链队列的结点定义 */
typedef struct QNode
{
    DataType data;            
    struct QNode *next;        
}LQNode,*PQNode ;
/* 链队列的定义 */
typedef struct 
{ 
    PQNode front, rear;        // 链队列的队头和队尾指针
}LinkQueue;

函数接口定义:

int JudgePalindrome(LinkStack st,LinkQueue qu);

st 和 qu 都是用户传入的参数, 其中st 是链栈的头指针,qu 是链队列的头指针。如果是回文字符串,则函数返回2,反之返回-1。

裁判测试程序样例:

#include <stdio.h>
#include <stdlib.h>
typedef char DataType;
typedef struct SNode
{  
    DataType data;            
    struct SNode *next;        
}SNode,*LinkStack;            
int InitLinkStack( LinkStack *top )
{
    *top = (LinkStack)malloc( sizeof(SNode) );
    if( *top == NULL ) 
    { 
        printf("初始化链栈出错");
        return 0;    
    }
    (*top)->next = NULL;
    return  1;
}
int LinkStackEmpty( LinkStack top )
{
    if( top->next == NULL ) 
        return 1;
    else
        return 0;
}
int Push(LinkStack top, DataType e)
{
    SNode *p;
    p = (SNode*)malloc(sizeof(SNode));
    if (!p)
    {
        printf("入栈操作出错!\n");
        return 0;
    }
    p->data = e;
    p->next = top->next;
    top->next = p;
    return 1;
}
int Pop(LinkStack top, DataType *e)
{
    SNode *p;
    if (!top->next)
    {
        printf("栈已空,无法完成出栈操作!\n");
        return 0;
    }
    p = top->next;
    top->next = p->next;
    *e = p->data;
    free(p);
    return 1;
}
int Destroy(LinkStack top)
{
    SNode *p;
    while (top)
    {
        p = top;
        top = top->next;
        free(p);
    }
    return 1;
}
typedef struct QNode
{
    DataType data;            
    struct QNode *next;        
}LQNode,*PQNode ;
typedef struct 
{ 
    PQNode front, rear;        
}LinkQueue;
int InitLinkQueue(LinkQueue* Q)
{
    Q->front = Q->rear = (PQNode)malloc(sizeof(LQNode));
    if (!Q->front)
    {
        printf("初始化队列失败!\n");
        return 0;
    }
    Q->front->next = NULL;
    return 1;
}
int LinkQueueEmpty(LinkQueue Q)
{
    if (Q.front == Q.rear) return 1;
    else return 0;
}
int EnLinkQueue(LinkQueue* Q, DataType e)
{
    PQNode p;
    p = (PQNode)malloc(sizeof(LQNode));
    if (!p)
    {
        printf("内存分配失败,不能完成入队操作!\n");
        return 0;
    }
    p->data = e;
    p->next = NULL;//初始化入队结点
    Q->rear->next = p;
    Q->rear = p;
    return 1;
}
int DeLinkQueue(LinkQueue* Q, DataType* e)
{
    PQNode p;
    if (Q->front == Q->rear)
    {
        printf("队列已空,不能完成出队操作!\n");
        return 0;
    }
    p = Q->front->next;
    *e = p->data;
    Q->front->next = p->next;
    free(p);
    if (Q->rear == p) //若删除的队列是最后一个结点,则移动队尾指针
    {
        Q->rear = Q->front;
    }
    return 1;
}
int DestroyLinkQueue(LinkQueue* Q)
{
    while (Q->front)
    {
        Q->rear = Q->front->next;
        free(Q->front);
        Q->front = Q->rear;

    }
    return 1;
}
/* 本题要求函数 */
int JudgePalindrome(LinkStack st,LinkQueue qu);
int main()
{
    LinkStack s;
    LinkQueue q;
    char ch;
    int rst;
    InitLinkStack(&s);
    InitLinkQueue(&q);
    while((ch=getchar())!='\n')
    {
        Push(s,ch);
        EnLinkQueue(&q,ch);
    }
    rst = JudgePalindrome(s,q);
    if ( rst == -1 )
    {
        printf("不是回文字符串\n");
    } 
    else if ( rst == 2 )
    {
        printf("是回文字符串\n");
    }
    Destroy(s);
    DestroyLinkQueue(&q);
    return 0;
}

/* 请在这里填写答案 */

输入样例:

asdfghjklkjhgfdsa

输出样例:

是回文字符串
  • 8
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在Python中,我们可以使用比较运算符来比较两个字符串的大小。比较运算符包括“==”(等于)、“!=”(不等于)、“<”(小于)、“>”(大于)、“<=”(小于等于)和“>=”(大于等于)。 字符串的比较是基于Unicode字符编码的。具体而言,字符串中的每个字符都有一个对应的Unicode编码,比较时会按照字符的Unicode值进行比较。首先比较第一个字符,如果相等则继续比较下一个字符,直到找到不相等的字符,或者比较完所有字符为止。 比较运算符比较的是字符串的大小,也就是按字典序进行比较。字典序是一种对字符或字符串进行排序的方式,即按字符的Unicode值从小到大排序。如果两个字符串的长度不同,那么较短的字符串在长度范围内都小于较长的字符串。 需要注意的是,在字符串比较时,大小写字母被视为不同的字符。如果我们希望进行不区分大小写的字符串比较,可以将字符串都转换为大写或小写再进行比较。 下面是一些示例: str1 = "abc" str2 = "def" if str1 == str2: print("字符串相等") elif str1 < str2: print("str1小于str2") else: print("str1大于str2") 输出结果为"str1小于str2",因为按字典序,字母"a"的Unicode值小于字母"d"的Unicode值。 综上所述,字符串的比较是根据字符的Unicode编码进行的,按照字典序进行比较。你可以使用比较运算符来判断字符串的大小关系。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值