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

Printing the second half of a linked list in reverse order

本文关键字:链表 后半部 打印 顺序      更新时间:2023-10-16

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

如果元素是: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';
}

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

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   

工作代码在这里: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均匀时两次打印中间位置。

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

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

您没有将最后一个数字添加到stack

这种方法可以工作...声明一个函数以获取链接列表的大小

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;

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

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

遍历电流将是一种更好的方法,因为这会在最后一个节点之后停止一个节点。

另请注意,这将对您的中点计算产生影响,因为它从一开始就偏离了 1。

它不会完全编译,但这行更少:

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