zoukankan      html  css  js  c++  java
  • 算法题:合并两个有序列表

    说明:这篇文章是学习交流,转载请注明出处。欢迎转载!

                 题目:已知有两个有序的单链表,其头指针分别为head1和head2。实现将这两个链表合并的函数:

              Node* ListMerge(Node *head1,Node *head2)

           这个算法非常像我们排序算法中的归并排序。仅仅能说“非常像”,由于思想是一样的,可是这个与归并排序还是有差别的。差别例如以下:

           1.归并排序是针对有序数组。而这里是有序链表;

           2.归并排序排序的时间复杂度为o(nlogn),而这里的时间复杂度最坏情况下为O(m+n),最好的情况下为O(min{m,n})。

           3.归并排序须要又一次申请空间,而这里无需再又一次申请空间。仅仅需改变链表结点的指针指向。

           而这里算法的思想跟归并排序是一样的,都是对两个待归并的线性表分别设置1个指针,比較这两个当前指针的大小,将小的结点加入到合并后的线性表中,并向后移动当前指针。若两个线性表中。至少有一个表扫描完。走将相应的还有一个表之间总体加入到合并后的线性表中。在这里:链表和数组的差别在于,链表仅仅须要改变当前合并序列尾指针的位置。而数组则要将剩下的值依次拷贝到归并表的尾部

            算法的递归实现例如以下:

    Node *ListMerge1(Node *head1,Node *head2)//採用递归的方法实现
    {
    	if(head1==NULL)
    		return head2;
    	if(head2==NULL)
    		return head1;
    	Node *head=NULL;
    	if(head1->value < head2->value)
    	{
    		head=head1;
    		head->next=ListMerge1(head1->next,head2);
    	}
    	else
    	{
    		head=head2;
    		head->next=ListMerge1(head1,head2->next);
    	}
    	return head;
    }

             算法的非递归实现例如以下:

    Node *ListMerge(Node *head1,Node *head2)
    {
    	if(!head1) return head2;
    	if(!head2) return head1;
    	Node *head=NULL;//合并后的头指针
    	Node *p1=head1;//p1用于扫描链表1
    	Node *p2=head2;//p2用于扫描链表2
    	if(head1->value<head2->value)
    	{
    		head=head1;
    		p1=head1->next;
    	}
    	else
    	{
    		head=head2;
    		p2=head2->next;
    	}
    	Node *p=head;//p永远指向最新合并的结点
    	while(p1 && p2)//假设循环停止。则p1或p2至少有一个为NULL
    	{
    		if(p1->value<p2->value)
    		{
    			p->next=p1;
    			p1=p1->next;
    		}
    		else
    		{
    			p->next=p2;
    			p2=p2->next;
    		}
    		p=p->next;
    	}
    	if(p1)//假设链1还没走完
    	{
    		p->next=p1;
    	}
    	else if(p2)//假设链2还没走完
    	{
    		p->next=p2;
    	}
    	return head;
    }

              整个測试代码例如以下:

    #include<iostream>
    using namespace std;
    struct Node
    {
    	int value;
    	Node* next;
    	Node(int v):value(v){}
    };
    /*创建一个链表,1->2->3->4->5->6->7*/
    Node* CreateList1()//创建一个有序的单链表1
    {
       Node *head;
       Node *n1=new Node(1);
       Node *n3=new Node(3);
       Node *n5=new Node(5);
       Node *n7=new Node(7);
       Node *n9=new Node(9);
       head=n1;
       n1->next=n3;
       n3->next=n5;
       n5->next=n7;
       n7->next=n9;
       n9->next=NULL;
       return head;
    }
    Node* CreateList2()//创建一个有序的单链表2
    {
       Node *head;
       Node *n2=new Node(2);
       Node *n4=new Node(4);
       Node *n6=new Node(6);
       Node *n8=new Node(8);
       head=n2;
       n2->next=n4;
       n4->next=n6;
       n6->next=n8;
       n8->next=NULL;
       return head;
    }
    void FreeList(Node *head)//将链表空间释放
    {
    	if(head==NULL)
    	{
    		return ;
    	}
    	else
    	{
    		Node *temp=head->next;
    		delete head;
    		head=temp;
    		FreeList(head);
    	}
    }
    
    void VisitList(Node *head)//遍历链表中的元素,用递归的方法遍历
    {
    	if(head)
    	{
    		cout<<head->value<<"->";
    		VisitList(head->next);
    	}
    	else
    	{
    		cout<<"null"<<endl;
    	}
    }
    Node *ListMerge(Node *head1,Node *head2)
    {
    	if(!head1) return head2;
    	if(!head2) return head1;
    	Node *head=NULL;//合并后的头指针
    	Node *p1=head1;//p1用于扫描链表1
    	Node *p2=head2;//p2用于扫描链表2
    	if(head1->value<head2->value)
    	{
    		head=head1;
    		p1=head1->next;
    	}
    	else
    	{
    		head=head2;
    		p2=head2->next;
    	}
    	Node *p=head;//p永远指向最新合并的结点
    	while(p1 && p2)//假设循环停止。则p1或p2至少有一个为NULL
    	{
    		if(p1->value<p2->value)
    		{
    			p->next=p1;
    			p1=p1->next;
    		}
    		else
    		{
    			p->next=p2;
    			p2=p2->next;
    		}
    		p=p->next;
    	}
    	if(p1)//假设链1还没走完
    	{
    		p->next=p1;
    	}
    	else if(p2)//假设链2还没走完
    	{
    		p->next=p2;
    	}
    	return head;
    }
    
    Node *ListMerge1(Node *head1,Node *head2)//採用递归的方法实现
    {
    	if(head1==NULL)
    		return head2;
    	if(head2==NULL)
    		return head1;
    	Node *head=NULL;
    	if(head1->value < head2->value)
    	{
    		head=head1;
    		head->next=ListMerge1(head1->next,head2);
    	}
    	else
    	{
    		head=head2;
    		head->next=ListMerge1(head1,head2->next);
    	}
    	return head;
    }
    int main()
    {
    	Node *head1=CreateList1();
    	Node *head2=CreateList2();
    	cout<<"归并前"<<endl;
    	cout<<"链表1:";
    	VisitList(head1);
    	cout<<"链表2:";
    	VisitList(head2);
    	cout<<"合并后的链表:";
    	//Node *head=ListMerge(head1,head2);
    	Node *head=ListMerge1(head1,head2);
    	VisitList(head);
    	FreeList(head);
    	return 0;
    }

              測试结果例如以下:


    參测试数据-------------《剑指offer》

    版权声明:本文博主原创文章。博客,未经同意,不得转载。

  • 相关阅读:
    chrome视频播放加速
    centos磁盘空间重新分配
    mseed2sac的安装和使用
    查找台站信息得到台站数据的网站
    java install
    CMT learning
    hosts持续更新
    what is SVD and how to calculate it
    google 镜像
    z变换
  • 原文地址:https://www.cnblogs.com/hrhguanli/p/4758321.html
Copyright © 2011-2022 走看看