您的位置:首页 > 职场人生

每日微软面试题——day 5

2011-08-11 03:48 666 查看
<以下微软面试题全来自网络>

<以下答案与分析纯属个人观点,不足之处,还望不吝指出^_^>

<版权所有,转载不忘注明出处:http://blog.csdn.net/zhanxinhang>

题:两个链表,一升一降。合并为一个升序链表。

分析假设升序的链表为链表1,降序的链表为链表2,p1,p2分别作为它们的迭代器,还有一个合并链表用于存放合并后的数据

法一、最容易想到的且容易实现的就是使两个表都变成升序,然后就是经典的合并排序算法的步骤了,步骤是构建p1,p2两个迭代器,分别用于迭代两个链表,每次遍历,若p1所指的节点数据大于p2所指的节点数据则将p1所指的节点数据插入到要合并链表中去且使p1指向下一个节点,否则将p2将所指的节点数据插入到合并链表中去且使p2指向下一个节点,直到p1和p2任意一个指向了NULL为止。最后可能两个链表中尚有剩余的节点,将其逐个插入到合并链表中去即可。

法二、使用递归方法后序遍历降序链表2,遍历顺序就相当于升序的顺序了。在递归遍历链表2的过程中,需要处理有以下三件事:(注意顺序)

(1) 如果p2的数据小于p1的就插入到合并链表中

(2) 如果p2的数据大于p1,那么就对链表1循环遍历,每次将p1中的数据插到合并链表中,直到p2不大于p1,且p1不为空


(3) 如果p1为空,就直接将p2插入到合并链表中


(这个方法你想到了没!)

完整实现代码:

/**
Author:花心龟
Blog:http://blog.csdn.net/zhanxinhang
**/

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>

typedef struct list_node
{
int data;
struct list_node * next;
}list_node;

list_node *list1=NULL; //链表头结点
list_node *list2=NULL; //链表头结点

void list_print(const list_node *p)//打印该链表函数
{
if(p==NULL)return;
while(p!=NULL)
{
printf("%d ",p->data);
p=p->next;
}
printf("\n");
}

void list_create(list_node* &head, int data[], int N)
{
if(data == NULL) return;

int i;
list_node *p;
p = (list_node*)malloc(sizeof(list_node));
p->data = data[0];
p->next = NULL;
head = p;
for(i=1;i<N; i++)
{
p->next = (list_node*)malloc(sizeof(list_node));
p->next->data = data[i];
p->next->next = NULL;
p=p->next;
}
}

void list_reverse(list_node* &head)  //使链表反序
{
if(head == NULL) return ;//如果head1为空,则返回
list_node *p,*q;
q=head;
p=head->next;

while(p!=NULL)
{
head->next=p->next; //将头指针的next指向p的下一个节点
p->next=q;          //将p的next值反指向它的前一个节点q
q=p;                //q移向p的位置
p=head->next;       //p移向它的下一个位置
}

head = q;
}

void list_destroy(list_node *head)  //销毁函数
{
list_node *pmove=NULL,*pdel=NULL;
pmove=head;

while(pmove!=head)
{
pdel=pmove;
free(pdel);
pmove=pmove->next;
}
}

list_node* merge_two_list() //合并链表1和链表2(法一)
{
list_reverse(list2);    //反转链表使之与链表一样升序排列
list_node *list_merged;  //和并后的链表
list_node *p1,*p2,*p0;
list_merged = (list_node*)malloc(sizeof(list_node));
list_merged->data = 0;
list_merged->next = NULL;
p0 = list_merged;

p1=list1;
p2=list2;
while(p1!=NULL && p2!=NULL)
{
if(p1->data < p2->data)
{
p0->next=(list_node*)malloc(sizeof(list_node));
p0->next->data=p1->data;
p0->next->next=NULL;
p0=p0->next;
p1=p1->next;
}
else
{
p0->next=(list_node*)malloc(sizeof(list_node));
p0->next->data=p2->data;
p0->next->next=NULL;
p0=p0->next;
p2=p2->next;
}
}
while(p1!=NULL)
{
p0->next=(list_node*)malloc(sizeof(list_node));
p0->next->data=p1->data;
p0->next->next=NULL;
p0=p0->next;
p1=p1->next;
}
while(p2!=NULL)
{
p0->next=(list_node*)malloc(sizeof(list_node));
p0->next->data=p2->data;
p0->next->next=NULL;
p0=p0->next;
p2=p2->next;
}
return list_merged;
}

list_node* p0=(list_node*)malloc(sizeof(list_node));
list_node* phead=p0;
list_node* &p1=list1; //p1与list1绑定
list_node* foreach(list_node* p2) //递归合并(法二)
{
if(p2==NULL) return phead;

foreach(p2->next);

if(p1->data > p2->data)
{
p0->next = (list_node*)malloc(sizeof(list_node));
p0->next->data = p2->data;
p0->next->next = NULL;
p0=p0->next;
return phead;
}
while(p1!=NULL && p1->data<=p2->data)
{
p0->next = (list_node*)malloc(sizeof(list_node));
p0->next->data = p1->data;
p0->next->next = NULL;
p0=p0->next;
p1 = p1->next;
}
if(p1==NULL)
{
p0->next = (list_node*)malloc(sizeof(list_node));
p0->next->data = p2->data;
p0->next->next = NULL;
p0=p0->next;
}

return phead;
}
//Blog:http://blog.csdn.net/zhanxinhang
int main()
{
int list1_data[] = {1,4,6,8,10};    //链表数据升序 可在这里该数据进行测试
int list2_data[] = {14,9,3,2};      //链表数据降序

list_create(list1,list1_data,5);   //构建单链表
list_create(list2,list2_data,4);   //构建单链表
list_print(list1);
list_print(list2);

//list_node *list_merged=merge_two_list(); //合并两个链表
//list_print(list_merged->next);      //打印合并后的链表

list_node *list_merged2=foreach(list2);    //使用递归合并两个链表
list_print(list_merged2->next);

list_destroy(list1);                //销毁链表
list_destroy(list2);                //销毁链表
//	list_destroy(list_merged);          //销毁合并后的链表
list_destroy(list_merged2);         //销毁合并后的链表
system("pause");
return 0;
}




:如何删除链表的倒数第m的元素?

分析:构建p0,p1两个迭代器,初始使p0和p1指向头结点,接着使p1移动到第m+1项,然后指向头得p0与p1同时前进,当p1指向空节点的时候结束,这时p0所指的位置就是倒数第m个,时间复杂度为O(n)

实现代码:(为了学习的需要,现在C++朋友采用c++实现,不能满足c朋友要采用c实现的愿望,此实为c++朋友的遗憾,不过一切重在思想。^_^)

/**
Author:花心龟
Blog:http://blog.csdn.net/zhanxinhang
**/
#include <iostream>
#include <list>
using namespace std;

class App
{
list<int> *plist;

void delete_node_at_last(int m) //today`s topic
{
list<int>::iterator p0, p1;
p0=p1=p2=plist->begin();

//使p1移到第m+1项
for(int i=1; i<=m; i++)
p1++;

//p0和p1同时前进,当p1到达终点时p0所指向的就是倒数第m个节点
while(p1!=plist->end())
p0++,p1++;

//删除节点
plist->erase(p0);
}

void create_list()
{
int list_data[]={1,2,3,4,5,6,7,8,9}; //链表数据
plist = new list<int>(list_data, list_data+sizeof(list_data)/sizeof(int));
}

void print_list()
{
list<int>::iterator it;
for(it=plist->begin(); it!=plist->end(); it++)
cout<<*it<<' ';
}

public:
//test in run funtion
void run()
{
create_list();
delete_node_at_last(3); //删除倒数第三个节点
print_list();
}

~App()
{
delete plist;
}
};
//Blog:http://blog.csdn.net/zhanxinhang
int main()
{
App myapp;
myapp.run();
system("pause");
return 0;
}


上一篇:每日微软面试题——day
4 (最长等差数列)

=======
welcome to my HomePage(http://blog.csdn.net/zhanxinhang)
to have a communication =======
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: