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

时间:2017-03-29 20:26:15

标签: c++ linked-list

我想打印链表的元素,首先按顺序打印,然后,一旦我到达中间,按相反顺序打印(从最后一个向后)。例如:

如果元素是:1 2 3 4 5 6
它应该打印:1 2 3 6 5 4
但它正在打印:1 2 3 5 4

为什么不打印最后一个元素?怎么解决这个问题?

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';
}

6 个答案:

答案 0 :(得分:1)

假设列表只包含一个元素。在这种情况下,这个循环

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

将永远不会执行,因此堆栈将为空。此外,当列表依次为空时,函数最初具有未定义的行为,因此head等于NULL,您可能无法访问current->next数据成员。

现在让我们假设该列表恰好包含两个元素。循环只执行一次,变量c得到值2.变量mid的计算值将等于1.

所以这个循环

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();


  }

意愿;永远不会因为条件i > 1产生false而执行,因为mid等于1。

因此程序有两个应该重写的错误循环。

下面是一个演示程序,展示了如何实现该功能。

#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;
}

程序输出

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   

答案 1 :(得分:0)

while循环中,您正在检查current->next是否null,您需要检查current是否为null

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

您没有将最后一个号码添加到stack

答案 2 :(得分:0)

此方法可以工作...声明一个函数来获取linkList的大小

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

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

    return counter;
}

然后如果返回的大小是偶数......

int c = size()/2;

其他......

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

然后初始化和数组并反向打印它们......尝试一下可能会有效:)

答案 3 :(得分:0)

在典型的链表实现中,最后一个节点指向空(通常为nullptr)。因此,将现有元素(current-&gt; next!= nullptr)添加到堆栈的停止条件不包括最后一个元素。

迭代当前将是一种更好的方法,因为它会在最后一个节点之后停止一个。

另请注意,这会对您的中点计算产生影响,因为它从一开始就被一个关闭。

答案 4 :(得分:0)

这不太适合编译,但是线条要少一些:

// 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());
}

答案 5 :(得分:0)

这里的工作代码: http://ideone.com/bbzsSy

2个问题:

  • while(current->next!=NULL)应该是:while(current!=NULL)
    通过这种方式,您可以确保可以取消引用指针,另外还可以推送最后一个节点。

  • for(int i=0;i<mid;i++)应该是:for(int i=0;i<lastFordward;i++)
    lastFordward=(c%2)?mid-1:mid; 这样就可以避免在c为偶数时打印中间位置两次。