繁体   English   中英

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

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

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

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

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

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

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

此方法可以工作...声明一个函数以获取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;

然后初始化和数组,然后反向打印它们。尝试一下可能会起作用:)

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

在电流上进行迭代将是更好的方法,因为它将在最后一个节点之后停止。

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

它并不会完全编译,但这会减少一些行:

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

此处的工作代码: 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为偶数时两次打印中间位置。

暂无
暂无

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

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