简体   繁体   English

以相反的顺序打印链接列表的后半部分

[英]Printing the second half of a linked list in reverse order

I want to print the elements of a linked list, first in their order and then, once I reach the middle, in reverse order (from the last one backwards). 我想按顺序打印链表中的元素,然后,一旦到达中间,就以相反的顺序(从最后一个倒退)打印。 For example: 例如:

If the elements are: 1 2 3 4 5 6 如果元素是: 1 2 3 4 5 6
It should print: 1 2 3 6 5 4 它应该打印: 1 2 3 6 5 4
But it's printing: 1 2 3 5 4 但它正在打印: 1 2 3 5 4

Why isn't it printing the last element? 为什么不打印最后一个元素? How can this be solved? 如何解决呢?

void reverse()
{
    int c=1;
    node *current,*prev,*temp;
    current=head;
    prev=NULL;
    std::stack<int>s;
    while(current->next!=NULL)
    {
        c++;
        s.push(current->data);
        current=current->next;
    }

    int mid=0;
    if((c%2)==0)
    {
        mid=c/2;
    }
    else
    {
        mid=(c+1)/2;
    }
    current=head;
    for(int i=0;i<mid;i++)
    {
        cout<<current->data<<"\t";
        current=current->next;
    }

    for(int i=mid;i>1;i--)
    {
       std::cout<<s.top()<<"\t";
       s.pop();
    }
    std::cout << '\n';
}

Let's assume that the list contains only one element. 假设列表仅包含一个元素。 In this case this loop 在这种情况下,此循环

while(current->next!=NULL)
{
    c++;
    s.push(current->data);
    current=current->next;
}

will be executed never and as result the stack will be empty. 将永远不会执行,结果堆栈将为空。 Moreover the function initially has undefined behavior when the list in turn is empty and hence head is equal to NULL and you may not access current->next data member. 此外,当列表依次为空,因此head等于NULL并且您可能无法访问current->next数据成员时,该函数最初具有未定义的行为。

Well now let's assume that the list contains exactly two elements. 现在,让我们假设该列表恰好包含两个元素。 The loop will be executed only once and the variable c gets value 2. The calculated value of the variable mid will be equal to 1. 该循环仅执行一次,变量c获得值2。变量mid的计算值等于1。

So this loop 所以这个循环

for(int i=0;i<mid;i++)
{
    cout<<current->data<<"\t";
    current=current->next;
}

executes only one iteration and the first element is outputted. 仅执行一次迭代,然后输出第一个元素。

However the next loop 但是下一个循环

  for(int i=mid;i>1;i--)
  {
     std::cout<<s.top()<<"\t";
     s.pop();


  }

will; 将; be executed never because its condition i > 1 yields false because mid is equal to 1. 永远不会因为其条件i > 1产生false而被执行,因为mid等于1。

So the program has two wrong loops that should be rewritten. 因此该程序有两个错误的循环,应该重写。

Below is a demonstrative program that shows how the function can be implemented. 下面是一个演示程序,显示了如何实现该功能。

#include <iostream>
#include <stack>

struct node
{
    int data;
    node *next;
} *head = nullptr;

void append( int data )
{
    node **current = &head;

    while ( *current ) current = &( *current )->next;

    *current = new node { data, nullptr };
}

void clear()
{
    while ( head )
    {
        node *tmp = head;
        head = head->next;
        delete tmp;
    }
}

void reverse()
{
    std::stack<int> s;

    for ( node *current = head; current; current = current->next )
    {
        s.push( current->data );
    }

    std::stack<int>::size_type middle = ( s.size() + 1 ) / 2;
    std::stack<int>::size_type i = 0;

    for ( node *current = head; i < middle; i++ )
    {
        std::cout << current->data << '\t';
        current = current->next;
    }

    for ( i = s.size() - i; i != 0; i-- )
    {
        std::cout << s.top() << '\t';
        s.pop();
    }

    std::cout << std::endl;
}

int main() 
{
    const int N = 10;

    for ( int i = 0; i < N; i++ )
    {
        for ( int j = 0; j <= i; j++ ) append( j );
        reverse();
        clear();
        std::cout << std::endl;
    }

    return 0;
}

The program output is 程序输出为

0   

0   1   

0   1   2   

0   1   3   2   

0   1   2   4   3   

0   1   2   5   4   3   

0   1   2   3   6   5   4   

0   1   2   3   7   6   5   4   

0   1   2   3   4   8   7   6   5   

0   1   2   3   4   9   8   7   6   5   

In your while loop you are checking if current->next is null you need to check if current is null . while循环中,您正在检查current->next是否为null您需要检查current是否为null

while(current)
{
    c++;
    s.push(current->data);
    current=current->next;
}

You weren't adding the last number into the stack 您没有将最后一个数字添加到stack

This method can work ... declare a function to get the size of the linkList 此方法可以工作...声明一个函数以获取linkList的大小

public int size()
{
    int counter = 0;
    node *nodePtr = head;

    while (nodePtr)
    {
        if (nodePtr->next != null)
        {
            counter++;
        }
    }

    return counter;
}

then if size returned is an even number ... 那么如果返回的大小是偶数...

int c = size()/2;

else ... 否则...

int c = (size()+1)/2;

then initialize and array and print them in reverse .... try it out might work :) 然后初始化和数组,然后反向打印它们。尝试一下可能会起作用:)

In a typical linked list implementation the last node points to nothing (typically nullptr). 在典型的链表实现中,最后一个节点不指向任何内容(通常为nullptr)。 Your stop condition for adding the existing elements (current->next!=nullptr) to the stack therefore doesn't include the last element. 因此,您将现有元素添加到堆栈的停止条件(current-> next!= nullptr)不包含最后一个元素。

Iterating over current would be a better approach as that would stop one after the last node. 在电流上进行迭代将是更好的方法,因为它将在最后一个节点之后停止。

Also note that this will have an impact on your mid-point calculation as it is off by one from the start. 还要注意,这将对您的中点计算产生影响,因为它从一开始就偏离了一个。

It's not quite going to compile, but this is somewhat fewer lines: 它并不会完全编译,但这会减少一些行:

// assert myList is sorted before called
// if it's not, add       
// std::sort(myList.begin(), myList.end());
// as the first line of the function
void reverseLatterHalf(std::vector& myList)  {
  auto it = myList.begin() + myList.size() / 2;
  std::reverse(it, myList.end());
}

Working code here: http://ideone.com/bbzsSy 此处的工作代码: http : //ideone.com/bbzsSy

2 issues: 2个问题:

  • while(current->next!=NULL) should be: while(current!=NULL) while(current->next!=NULL)应该是: while(current!=NULL)
    This way you be sure that you can dereferencing the pointer, plus you also push the last node. 这样,您可以确保可以取消引用指针,并且还可以推送最后一个节点。

  • for(int i=0;i<mid;i++) should be: for(int i=0;i<lastFordward;i++) for(int i=0;i<mid;i++)应该是: for(int i=0;i<lastFordward;i++)
    Where lastFordward=(c%2)?mid-1:mid; 其中lastFordward=(c%2)?mid-1:mid;
    This way avoid to print the mid position twice when c is even. 这样可以避免在c为偶数时两次打印中间位置。

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

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