#include <iostream>
using namespace std;
struct ListNode
{
char data;
ListNode *next;
}*head = NULL, *nodeptr = NULL, *newNode = NULL;
bool isPalindrome(ListNode*);
int main()
{
char pali[] = "abaaba";//array of chars
for (int i = 0; pali[i] != '\0'; i++)
{
newNode = new ListNode;
newNode -> data = pali[i]; //places chars into a linked list
newNode -> next = head;
head = newNode;// links list together
nodeptr = head;
while(nodeptr != NULL)// prints out the chars
{
cout << nodeptr -> data;
nodeptr = nodeptr ->next;
}
cout << endl;
if(isPalindrome(head)) //prints if function true
cout << "Is a Palindrome" << endl;
else if(!isPalindrome(head)) //prints if function false
cout << "Not a Palindrome" << endl;
}
return 0;
}
//test if the list is a palindrome
bool isPalindrome(ListNode* headptr)
{
ListNode* topptr = headptr;//intializes to first char
ListNode* botptr = headptr;//intializes to first char
ListNode* temp = NULL;
if(headptr != NULL && headptr -> next != NULL )//uses to initially test if the list is empty or a singleton
{
while(botptr->next != NULL)//places botptr at the last value pointing towards null
{
//cout << botptr ->data;
botptr = botptr -> next ;
}
while (topptr != temp || topptr -> next != temp ) //reiterates until the list is the same as temp(empty) or if the next topptr(headptr) value is temp(singleton)
{
if(topptr -> data != botptr -> data)//stops if two values dont equal. I feel like the main problem is with this comparison.
{
return false;
}
else if(botptr -> data == topptr -> data)//if two values do equal move topptr and botptr towards the middle by one.
{
temp = topptr;
temp = topptr-> next;
topptr = temp;//moves topptr down by one
temp = botptr;
botptr = topptr; //intializes botptr to the first in the next iteration
while(botptr -> next != temp)
{
botptr = botptr -> next;// move botptr up by one
}//places bottom pointer onto the last value pointer towards null or temp
}
}
}
return true; // returns true if only the list is empty or a singleton
}
我很难找出这个程序的问题。每次我运行它,它都会经历第三次迭代,然后崩溃。出于某种原因,我无法在第二次迭代中获得返回错误比较。当它应该循环为零时,它循环一次,因为topptr等于b,而botptr等于a。
答案 0 :(得分:0)
这一行看起来非常可疑:
while (topptr != temp || topptr -> next != temp ) //reiterates until the list is the same as temp(empty) or if the next topptr(headptr) value is temp(singleton)
temp
是一个临时变量,可用于多种用途(特别是topptr
的下一个值和botptr
后面的项目)。使用这样的变量进行内部范围之外的比较是危险的。
我相信这条线应该是这样的:
while (topptr != botptr && botptr -> next != topptr) //iterates until topptr reaches botptr
此外,我建议您在需要的范围内声明temp
变量。换句话说,删除行
ListNode* temp = NULL;
并将else if(botptr -> data == topptr -> data)
下方的行更改为
ListNode* temp = topptr;
答案 1 :(得分:0)
由于你做得有点不对劲,我写了更长的批评。如果你遵循它,你也会发现为什么你的程序不能一直工作。首先:
完全避开了,让我们来看看来源:
#include <iostream>
using namespace std;
这句话令人不悦:Why is "using namespace std" considered bad practice?
struct ListNode
{
char data;
ListNode *next;
}*head = NULL, *nodeptr = NULL, *newNode = NULL;
在这里,您全局声明三个变量,这些变量可以很容易地成为main的一部分。尽量减少每个声明变量的范围。
bool isPalindrome(ListNode*);
int main()
{
char pali[] = "abaaba";//array of chars
for (int i = 0; pali[i] != '\0'; i++)
像这样测试pali的结束条件是正确的,但是很麻烦。您可以轻松地测试pali[i]
。
{
newNode = new ListNode;
newNode -> data = pali[i]; //places chars into a linked list
newNode -> next = head;
head = newNode;// links list together
nodeptr = head;
因此,您的链接列表与输入字符串的顺序相反。鉴于问题没有错,但这是一种非常独特的方式来存储字符串。
此外,您将浏览添加到列表中的每个字符的整个算法(打印和所有内容)。我想这可能是出于调试目的而有意的。
while(nodeptr != NULL)// prints out the chars
{
cout << nodeptr -> data;
nodeptr = nodeptr ->next;
}
cout << endl;
if(isPalindrome(head)) //prints if function true
cout << "Is a Palindrome" << endl;
else if(!isPalindrome(head)) //prints if function false
cout << "Not a Palindrome" << endl;
第二次测试是多余的;只需完全删除整个if(!isPalindrome(head))
测试,只留下else
。有些东西要么是回文,要么没有,没有其他可能的结果。运行算法两次'以确保'只是浪费CPU周期。
}
return 0;
}
//test if the list is a palindrome
bool isPalindrome(ListNode* headptr)
{
ListNode* topptr = headptr;//intializes to first char
ListNode* botptr = headptr;//intializes to first char
ListNode* temp = NULL;
同样,最小化变量的范围。特别是'temp'可以降到它的使用位置。
if(headptr != NULL && headptr -> next != NULL )//uses to initially test if the list is empty or a singleton
同样,你使测试比他们需要的更麻烦。只需测试if (headptr && headptr->next)
,这就足够了。
{
while(botptr->next != NULL)//places botptr at the last value pointing towards null
{
//cout << botptr ->data;
botptr = botptr -> next ;
}
while (topptr != temp || topptr -> next != temp ) //reiterates until the list is the same as temp(empty) or if the next topptr(headptr) value is temp(singleton)
此测试指定不正确; '||'应该是'&amp;&amp;'。
{
if(topptr -> data != botptr -> data)//stops if two values dont equal. I feel like the main problem is with this comparison.
{
return false;
}
这种比较很好。
else if(botptr -> data == topptr -> data)//if two values do equal move topptr and botptr towards the middle by one.
{
然而,这种比较并非如此。你再次测试一个你已经知道必须是真实的条件。一个简单的'别人'就足够了。额外的if会浪费CPU周期并形成维护危险。
temp = topptr;
temp = topptr-> next;
topptr = temp;//moves topptr down by one
对同一个变量的双重赋值应始终让您感到怀疑。在这种情况下,两个任务都是不必要的;你可以简单地写topptr = topptr->next;
此外,如果topptr和bottomptr之前指向相邻的字符,它们现在将指向相同的字符。这将导致下一个while循环的结束条件永远不会成为真,导致程序崩溃。您需要一个额外的条件:
if (topptr == botptr)
return true;
temp = botptr;
botptr = topptr; //intializes botptr to the first in the next iteration
因为你有一个单链表,你不能轻易地将botptr移动到下一个最低位置。您需要再次遍历整个列表以查找新的botptr。因此,算法的运行时成本为O(n ^ 2),这意味着算法的成本是其输入大小的平方。在这种情况下,具有O(n)复杂度的算法是可能的,这是非常优选的。
while(botptr -> next != temp)
{
botptr = botptr -> next;// move botptr up by one
}//places bottom pointer onto the last value pointer towards null or temp
}
}
}
return true; // returns true if only the list is empty or a singleton
}
那么使用std :: string的解决方案是什么样的呢?这有点简单:
bool isPalindrome (const std::string &s) {
for (int b=0, e=s.size () - 1; b<e; b++, e--)
if (s [b] != s [e])
return false;
return true;
}
int main () {
if (isPalindrome ("abaaba"))
cout << "Is a Palindrome" << endl;
else
cout << "Not a Palindrome" << endl;
return 0;
}