1. 程式人生 > 程式設計 >c++ 如何合併兩個有序連結串列

c++ 如何合併兩個有序連結串列

1.題目要求

這是一道求職面試時經常要求手寫或者機試的經典題目。

已知兩個連結串列head1和head2各自有序,請把它們合併成一個連結串列依然有序。結果連結串列要包含head1和head2的所有節點,即使節點值相同。

注意:不能開闢新空間來儲存合併後的連結串列。如果第一次做該題,很容易會想到使用新連結串列來儲存合併後的有序連結串列。雖然可以如此實現,但是不符合常規解法和麵試官的要求。

2.非遞迴實現

演算法過程:
輸入:兩個有序的單鏈表head1與head2;
輸出:合併後的有序單鏈表mergeHead;
演算法描述:
(1)如果head1或head2為空連結串列,則直接返回另外一個連結串列;

(2)選擇head1與head2連結串列當前節點值較小的節點,掛接到後並後的連結串列mergeHead;
(3)重複步驟2,直到連結串列head1或者head2遍歷完成,未遍歷完的連結串列,直接掛接到mergeHead的尾節點。

具體實現如下:

#include <sstream>
#include <iostream>
using namespace std;

struct ListNode 
{ 
  int     value; 
  ListNode*  next;
  ListNode() {value=0;next=NULL;}
  ListNode(int value,ListNode* next = NULL):value(value),next(next){} 
};

//@brief:非遞迴實現兩個有序單鏈表
//@注意:兩個連結串列需要從小到大順序排列
ListNode* mergeOrderedLinkedList(ListNode* head1,ListNode* head2)
{
  if (head1 == NULL) 
  { 
    return head2; 
  }
  else if(head2 == NULL) 
  { 
    return head1; 
  }

  ListNode* mergeHead = NULL; 
  if (head1->value<head2->value) 
  { 
    mergeHead=head1;
    head1=head1->next;
  } 
  else 
  { 
    mergeHead = head2; 
    head2 = head2->next; 
  } 
  ListNode* tmpNode = mergeHead; 
  while(head1&&head2)
  { 
    if(head1->value<head2->value) 
    { 
      mergeHead->next = head1; 
      head1 = head1->next; 
    } 
    else 
    { 
      mergeHead->next = head2; 
      head2 = head2->next; 
    } 
    mergeHead = mergeHead->next; 
  } 
  if (head1)
  { 
    mergeHead->next = head1; 
  } 
  if (head2) 
  { 
    mergeHead->next = head2; 
  }

  return tmpNode; 
}

//列印連結串列
void printLinkedList(ListNode* head)
{
  while(head)
  {
    cout<<head->value<<" ";
    head=head->next;
  }
  cout<<endl;
}

int main(int argc,char* argv[])
{
  ListNode* head1=NULL,*curList1=NULL,*head2=NULL,*curList2=NULL;
  string strIn;
  int value;

  cout<<"建立連結串列1,從小到大順序輸入連結串列1:"<<endl;
  getline(cin,strIn);
  stringstream ss(strIn);
  cout<<"ss0 strIn:"<<ss.str()<<endl;
  while(ss>>value)    //從string中按照空格讀取int
  {
    ListNode* newNode1=new ListNode;
    newNode1->value=value;
    if(head1==NULL && curList1==NULL)
    {
      head1=newNode1;
      curList1=newNode1;
    }
    else
    {
      curList1->next=newNode1;
      curList1=curList1->next;
    }
  }

  cout<<"建立連結串列2,從小到大順序輸入連結串列2:"<<endl;
  getline(cin,strIn);
  ss.clear(); //清空狀態
  ss.str(""); //清空內容
  ss<<strIn;  //重新輸出至string
  cout<<"ss1 strIn:"<<ss.str()<<endl;
  while(ss>>value)    //從string中按照空格讀取int
  {
    ListNode* newNode2=new ListNode;
    newNode2->value=value;
    if(head2==NULL && curList2==NULL)
    {
      head2=newNode2;
      curList2=newNode2;
    }
    else
    {
      curList2->next=newNode2;
      curList2=curList2->next;
    }
  }

  //合併兩個有序連結串列
  ListNode* mergeHead=mergeOrderedLinkedList(head1,head2);

  //列印連結串列
  cout<<"合併後連結串列:"<<endl;
  printLinkedList(mergeHead);
}

執行程式,輸出結果:

從小到大順序輸入連結串列1:
1 2 3 5
ss0 strIn:1 2 3 5
從小到大順序輸入連結串列2:
3 4 5 6 7 8
ss1 strIn:3 4 5 6 7 8
合併後連結串列:
1 2 3 3 4 5 5 6 7 8

3.遞迴實現

從上面合併兩個有序連結串列的步驟中可以看出,每次合併的步驟(2)都是一樣的,由此我們想到了遞迴。具體實現如下:

//@brief:遞迴實現兩個有序單鏈表
//@注意:兩個連結串列需要從小到大順序排列
ListNode* mergeOrderedLinkedListRecursion(ListNode* head1,ListNode* head2)
{
  if(head1 == NULL) 
  { 
    return head2; 
  }
  else if(head2 == NULL) 
  { 
    return head1; 
  }

  ListNode* mergeHead = NULL;
  if(head1->value<head2->value) 
  {
    mergeHead=head1;
    mergeHead->next=mergeOrderedLinkedListRecursion(head1->next,head2);
  }
  else
  {
    mergeHead=head2;
    mergeHead->next=mergeOrderedLinkedListRecursion(head1,head2->next);
  }
  return mergeHead;
}

以上就是c++ 如何合併兩個有序連結串列的詳細內容,更多關於c++ 合併兩個有序連結串列的資料請關注我們其它相關文章!