微軟面試100題系列 一道合併連結串列問題的解答 第42題
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow
也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!
微軟面試100題V0.1版第42題 合併連結串列解答
July、網友 二零一一年一月2日
------------------------------------
本文參考:本人整理的微軟面試100題系列V0.1版第42題、網友的回覆。
本人宣告:本人對此微軟等100題系列任何資料享有版權。
由於微軟等面試100題系列的答案V0.2版,答案V0.3版[第1-40題答案]都已經放出,
而答案V0.3版最近新整理好,在上傳之前,選擇性的貼幾道題的答案,以讓讀者檢驗。
至於第1-40題的答案,日後,我也會不定期的選擇性的在我部落格裡一一闡述。
ok,第56題[最長公共子序列]的答案,已在我的博文:
24個經典算法系列:3、動態規劃演算法解微軟面試第56題 中明確闡述了。
這次,咱們來看一道連結串列合併的面試題。
42、請修改append函式,利用這個函式實現:兩個非降序連結串列的並集,
1->2->3 和 2->3->5 併為 1->2->3->5另外只能輸出結果,不能修改兩個連結串列的資料。
此題,合併連結串列,要求將倆個非有序排列的連結串列,有順序的合併。如下:
//程式一、引自一網友。
#include <stdio.h>
#include <malloc.h>
typedef struct lnode {
int data;
struct lnode *next;
}lnode,*linklist;
linklist creatlist(int m)//建立連結串列
{
linklist p,l,s;
int i;
p=l=(linklist)malloc(sizeof(lnode));
p->next=NULL;
printf("請輸入連結串列中的一個數字:");
scanf("%d",&p->data);
for(i=2;i<=m;i++)
{
s=(linklist)malloc(sizeof(lnode));
s->next = NULL;
printf("請輸入第%d個數字",i);
scanf("%d",&s->data);
p->next=s;
p=p->next;
}
printf("/n");
return l;
}
void print(linklist h)//列印連結串列
{
linklist p=h->next;
int t=1;
printf("列印各個數字:/n");
do
{
printf("請輸出第%d個數:",t);
printf("%d/n",p->data);
p=p->next;
t++;
}while(p);
}
linklist mergelist(void)//兩個連結串列合併
{
int e,n;
linklist pa,pb,pc,head;
printf("請輸入第一個連結串列的長度:");
scanf("%d",&e);
pa=creatlist(e);
printf("請輸入第二個連結串列的長度:");
scanf("%d",&n);
pb=creatlist(n);
head=pc=(linklist)malloc(sizeof(lnode));
pc->next=NULL;
while(pa&&pb)
{
if(pa->data<=pb->data)
{
pc->next=pa;
pc=pa;
pa=pa->next;
}
else
{
pc->next=pb;
pc=pb;
pb=pb->next;
}
}
pc->next=pa?pa:pb;
return head;
}
void main()
{
linklist head;
head=mergelist();
print(head);
}
///////////////////////////////////
請輸入第一個連結串列的長度:5
請輸入連結串列中的一個數字:3
請輸入第2個數字2
請輸入第3個數字1
請輸入第4個數字7
請輸入第5個數字9
請輸入第二個連結串列的長度:5
請輸入連結串列中的一個數字:6
請輸入第2個數字4
請輸入第3個數字5
請輸入第4個數字8
請輸入第5個數字7
列印各個數字:
請輸出第1個數:3
請輸出第2個數:2
請輸出第3個數:1
請輸出第4個數:6
請輸出第5個數:4
請輸出第6個數:5
請輸出第7個數:7
請輸出第8個數:8
請輸出第9個數:7
請輸出第10個數:9
Press any key to continue
//程式二、引用yangsen600。
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
struct Node
{
int num;
Node * next;
};
Node * createTail()
{
int x;
Node *head = NULL, *p = NULL, *tail = NULL;
puts("/nplease enter some digits(end of '.'):");
while( 1 == scanf("%d",&x) )
{
p = (Node *)malloc(sizeof(Node));
p->num = x;
p->next = NULL;
if( NULL == head )
{
tail = p;
head = tail;
}
else
{
tail->next = p;
tail = p;
}
}
getchar();
return head;
}
Node * CombinationNode(Node* head1, Node* head2)
{
Node *head,*tail,*p = head1,*q = head2,*s;
if( NULL == p )
return q;
if( NULL == q )
return p;
tail = p;
if( p->num > q->num)
tail = q;
head = tail;
while( NULL != p && NULL != q )
{
if(p->num <= q->num )
//如果p所指元素<q所指元素,那麼把p所指元素,率先拉入合併後的連結串列中,
//p賦給s,並從p的下一個元素p->next查詢。
//直到發現p所指 不再 < q,而是p > q了 即轉至下述程式碼的else部分。
{
s = p;
p = p->next;
}
else
{
s = q;
q = q->next;
}
tail->next = s;
tail = s;
}
if( NULL == p )
p = q;
s = p;
tail->next = s;
return head;
}
void printHead(Node *head)
{
if( NULL == head )
return;
printf("List: ");
while(head)
{
printf("%d->",head->num);
head = head->next;
}
puts("NUL");
}
void main( void )
{
Node* head1,*head2,*head;
head1 = createTail();
printHead(head1);
head2 = createTail();
printHead(head2);
head = CombinationNode(head1,head2);
printHead(head);
}
//////////////////////////////////////////
please enter some digits(end of '.'):
3 2 1 7 9.
List: 3->2->1->7->9->NUL
please enter some digits(end of '.'):
6 4 5 8 7.
List: 6->4->5->8->7->NUL
List: 3->2->1->6->4->5->7->8->7->9->NUL
Press any key to continue
//與上述那段,輸出結果一致。
42題的形式變化:
已知兩個連結串列head1 和head2 各自有序,請把它們合併成一個連結串列依然有序。
//程式三、非遞迴實現 連結串列合併排序:
Node * Merge(Node *head1 , Node *head2)
{
if ( head1 == NULL)
return head2 ;
if ( head2 == NULL)
return head1 ;
Node *head = NULL ;
Node *p1 = NULL;
Node *p2 = NULL;
if ( head1->data < head2->data )
{
head = head1 ;
p1 = head1->next;
p2 = head2 ;
}
else
{
head = head2 ;
p2 = head2->next ;
p1 = head1 ;
}
Node *pcurrent = head ;
while ( p1 != NULL && p2 != NULL)
{
if ( p1->data <= p2->data )
{
pcurrent->next = p1 ;
pcurrent = p1 ;
p1 = p1->next ;
}
else
{
pcurrent->next = p2 ;
pcurrent = p2 ;
p2 = p2->next ;
}
}
if ( p1 != NULL )
pcurrent->next = p1 ;
if ( p2 != NULL )
pcurrent->next = p2 ;
return head ;
}
//程式四、遞迴實現,
Node * MergeRecursive(Node *head1 , Node *head2)
{
if ( head1 == NULL )
return head2 ;
if ( head2 == NULL)
return head1 ;
Node *head = NULL ;
if ( head1->data < head2->data )
{
head = head1 ;
head->next = MergeRecursive(head1->next,head2);
}
else
{
head = head2 ;
head->next = MergeRecursive(head1,head2->next);
}
return head ;
}
--------------------------------------------------------------------------------------------------
ok,最後,咱們來透徹比較下上述幾段程式碼的相同與不同。
不放比較一下,程式一、和程式二關於連結串列合併的核心程式碼,的區別:
Node * CombinationNode(Node* head1, Node* head2) //程式二
{
Node *head,*tail,*p = head1,*q = head2,*s;
if( NULL == p )
return q;
if( NULL == q )
return p;
tail = p;
if( p->num > q->num)
tail = q;
head = tail;
while( NULL != p && NULL != q )
{
if(p->num <= q->num )
{
s = p; //3.4
p = p->next; //
}
else
{
s = q;
q = q->next;
}
tail->next = s;
tail = s;
}
if( NULL == p )
p = q;
s = p;
tail->next = s;
return head;
}
和這段:
linklist mergelist(void) //程式一
{
int e,n;
linklist pa,pb,pc,head;
printf("請輸入第一個連結串列的長度:");
scanf("%d",&e);
pa=creatlist(e);
printf("請輸入第二個連結串列的長度:");
scanf("%d",&n);
pb=creatlist(n);
head=pc=(linklist)malloc(sizeof(lnode)); //1.這
pc->next=NULL; //2.這
while(pa&&pb)
{
if(pa->data<=pb->data)
{
pc->next=pa; //3.這
pc=pa;
pa=pa->next;
}
else
{
pc->next=pb; //4.這
pc=pb;
pb=pb->next;
}
}
pc->next=pa?pa:pb;
return head;
}
再比較下,程式一與程式四倆段的形式區別:
linklist mergelist(void)//程式一
{
int e,n;
linklist pa,pb,pc,head;
printf("請輸入第一個連結串列的長度:");
scanf("%d",&e);
pa=creatlist(e);
printf("請輸入第二個連結串列的長度:");
scanf("%d",&n);
pb=creatlist(n);
head=pc=(linklist)malloc(sizeof(lnode));
pc->next=NULL;
while(pa&&pb)
{
if(pa->data<=pb->data)
{
pc->next=pa; //3
pc=pa; //1
pa=pa->next; //2
}
else
{
pc->next=pb;
pc=pb;
pb=pb->next;
}
}
pc->next=pa?pa:pb;
return head;
}
和
//遞迴實現,程式四
Node * MergeRecursive(Node *head1 , Node *head2)
{
if ( head1 == NULL )
return head2 ;
if ( head2 == NULL)
return head1 ;
Node *head = NULL ;
if ( head1->data < head2->data )
{
head = head1 ;
head->next = MergeRecursive(head1->next,head2);
}
else
{
head = head2 ;
head->next = MergeRecursive(head1,head2->next);
}
return head ;
}
------------------------------
//程式一標明的1、2、3相當於,下述程式四的1、2、3
if ( head1->data < head2->data )
{
head = head1 ; //1.head=head1;
head->next = MergeRecursive(head1->next,head2); //2.head1=head1->next;
//3.head->next=head1
}
else
{
head = head2 ;
head->next = MergeRecursive(head1,head2->next);
}
return head ;
聰明的你,相信,不要我過多解釋。:)。
作者宣告:
本人July對本部落格所有任何內容享有版權,轉載或引用任何內容、資料,
請註明作者本人 July及出處。謝謝。