简体   繁体   English

如何在C ++中检查整数单链列表的对称性?

[英]How to check the symmetry of an integer singly-linked list in C++?

I have a question about singly-linked list in C++. 我对C ++中的单链接列表有疑问。

An integer array[0..n] is called symmetric if array[0] = array[n], array[1] = array[n-1], ... 如果array [0] = array [n],array [1] = array [n-1],...,则整数array [0..n]被称为对称。

For example: 1 2 3 4 5 4 3 2 1 例如:1 2 3 4 5 4 3 2 1

So, is there any way to check the symmetry of an integer singly-linked list? 那么,有什么方法可以检查整数单链列表的对称性吗?

I've thought about copying the value of them downto an array then check the symmetry of this array but I think it is not good because the featured of link list will be lost. 我曾考虑过将它们的值复制到一个数组中,然后检查此数组的对称性,但我认为这样做不好,因为链接列表的功能将丢失。

If by "simple-linked" you actually mean singly linked, then you have to copy half of them - whether on the stack using recursion or to an array. 如果通过“简单链接”实际上是指链接,则必须复制它们的一半-无论是使用递归堆栈还是数组。

bool is_symmetric(Node* p, int n)
{
    Value values[n / 2]; // use alloca or std::vector if your compiler doesn't support
    for (int i = 0; i < n / 2; ++i, p = p->next)
         values[i] = p->value;
    if ((n + 1) % 2) p = p->next; // for odd number of elements, middle one's ok
    for (; i >= 0; --i, p = p->next)
         if (values[i] != p->value)
             return false;
    return true;
}

Note: I haven't tested this, and it might have an error or two, but the general idea's there.... 注意:我还没有测试过,它可能有一个或两个错误,但是总的思路就在那里。

If it's doubly linked, it's even easier - iterate half way then iterate in both directions doing the comparisons. 如果它是双向链接,则更容易-进行一半迭代,然后双向进行比较。

The classic way is to fold over the list and push elements on a stack until half way, then pop from the stack and compare with remaining elements. 经典的方法是将列表折叠并压入堆栈中的元素直到一半,然后从堆栈中弹出并与其余元素进行比较。

bool isPalindrome(forward_list<int> &l){
 forward_list<int> stack;
 auto it = l.begin();
 int len = 0;
 int i   = 0;
 while (it != l.end()){
   ++len;
   ++it;
 }
 if (len <= 1)
   return true;
 it = l.begin();
 while (i < (len / 2)) {
   stack.push_front(*it);
   ++i;
   ++it;
 }
 if ((len % 2) == 1) 
   ++it;
 while (!stack.empty()){
   if (stack.front() != *it)
     return false;
   stack.pop_front();
   ++it;
 }
 return true;
}

bool test_good(const int i){
 int j = i / 2;
 forward_list<int> l;
 for (int k = 0; k < j; k++){
   l.push_front(k); 
 }
 if (i % 2 == 1){
   l.push_front(j);
 }
 for (int k = j-1; k >= 0; k--){
   l.push_front(k);
 }
 return isPalindrome(l);
}

bool test_bad(const int i){
 forward_list<int> l;
 for (int k = 0; k < i; k++){
   l.push_front(k); 
 }
 l.push_front(i);
 l.push_front(i+1);
 return !isPalindrome(l);
}

int main(){
 for (int i = 0; i < 20; i++){
   cout << "test for " << i << "...";
   if (test_good(i))
     cout << "ok...";
   else return i;
   if (test_bad(i))
     cout << "ok." << endl;
   else return i;
 }

 return 0;
}

I used a forward_list to implement the stack, rather than using the dedicated std::stack template. 我使用forward_list实现堆栈,而不是使用专用的std::stack模板。 Also, note that the problem is trickier when using generic lists of T , since you don't necessarily want to instantiate copies of values in the list when pushing on the stack, but you can't push references to values of primitive types (like char or int ). 另外,请注意,使用T泛型列表时,此问题比较棘手,因为在推入堆栈时不必一定要实例化列表中值的副本,但是您不能将对原始类型值的引用(例如charint )。 For that problem, you would have to provide two different templated implementations, which would be enable_if ed according to what T is. 对于该问题,您将必须提供两个不同的模板化实现,这些实现将根据T是什么来enable_if You would probably also add the comparison operator to the template. 您可能还将比较运算符添加到模板中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM