簡體   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