线性表的合并(五大案例完整源代码分析)

目录
1.顺序有序表的合并
2.链式有序表的合并
3.不重复式合并
4.双递增合并一递减
5.稀疏多项式的合并
在这里插入图片描述

1.顺序有序表的合并

已知有两个有序集合A和B按照递增有序排列,现在有一个集合C =AUB,C也要按照递增有序排列,举例:A={3,5,8,11},B={2,6,8,9,11,15,20},那么C={2,3,5,6,8,8,9,11,11,15,20}

代码实现:

#include<iostream>
using namespace std; 
#define OK  1
#define ERROR 0
#define MAXSIZE 100 
#define Status int
typedef  int  ElemType;//这里是存入的数据类型
typedef  struct
{
	ElemType *elem;//这里可以是一个复杂的结构体数组 
	int length;//用于存储数组的长度 
}SqList;
Status InitList(SqList &L)//初始化顺序表 
{
	L.elem=new ElemType[MAXSIZE];//为顺序表分配空间 
	if(!L.elem)//分配不成功就退出 
	exit(0); 
	L.length=0;//空表的长度为0 
	return OK; 
} 
void ListTraverse(SqList L)//遍历元素 
{
	if(L.length==0)
	cout<<"0\n还没添加任何元素"<<endl; 
	else
	{
		 cout<<"当前顺序表的元素有:\n";
	for(int i=0;i<L.length;i++)
	{
	    cout<<L.elem[i]<<" ";
	} 
		
	}
}
Status CreateList(SqList &L,int n)//创建顺序表函数,初始化前几个元素 
{
	if(n<0||n>MAXSIZE)
	return ERROR;
	else{
		cout<<"请依次输入存入数据:";
			for(int i=0;i<n;i++)
	{
	    cin>>L.elem[i]; 
		L.length++;
	}
	return OK;	
	}
} 
void MergeList(SqList La,SqList Lb,SqList &Lc)
{
	Lc.length=La.length+Lb.length;
	Lc.elem=new ElemType[Lc.length];
	ElemType *pc=Lc.elem;//pc指向集合C的第一个元素 
	ElemType *pa=La.elem;//pa指向集合A的第一个元素 
	ElemType *pb=Lb.elem;//pb指向集合B的第一个元素 
	ElemType *pa_last=La.elem+La.length-1;//指向A集合的尾元素 
	ElemType *pb_last=Lb.elem+Lb.length-1;//指向B集合的尾元素 
	while((pa<=pa_last)&&(pb<=pb_last))
	{
		if(*pa<=*pb)//比较两个元素大小,小的在前大的在后 
		*pc++=*pa++;//赋值的同时指针向后移动 
		else
		*pc++=*pb++;
	}
	while(pa<=pa_last)//谁先结束谁再次循环 
	*pc++=*pa++;
	while(pb<=pb_last)
	*pc++=*pb++;
} 
int  main()
{
	SqList La;
	SqList Lb;
	SqList Lc;
	InitList(La);
	InitList(Lb);
	int n;
	int m;
	cout<<"请输入在表A中添加的元素个数:";
	cin>>n; 
	CreateList(La,n);
	cout<<"请输入在表B中添加的元素个数:";
	cin>>m; 
	CreateList(Lb,m);
	cout<<"两表合并后的表c元素依次为:"; 
	 MergeList(La,Lb,Lc);
	 ListTraverse(Lc);
}

运行结果:
在这里插入图片描述

2.链式有序表的合并

问题同2,我们使用链式结构:

#include<stdio.h>
#include<iostream>
using namespace std; 
#define OK  1
#define ERROR 0
#define MAXSIZE 100 
typedef  int  Status;
typedef  int  ElemType;
typedef struct LNode{
	ElemType data;
	struct LNode *next;
}LNode,*LinkList;
Status InitList(LinkList &L)//初始化单链表 
{
	L=new LNode;
	L->next=NULL;
	return OK;
}
void CreateList(LinkList &L,int n)//创建顺序表函数,初始化前几个元素 
{
	LinkList p,q;
	q=L;
	for(int i=n;i>0;i--)
	{
		p=new LNode;
		cin>>p->data;
		p->next=NULL;
		q->next=p;
		q=p;
	 } 
} 
void TraverseList_L(LinkList l)//遍历集合 
{
	l=l->next;
	while(l)
	{
		if(l->next!=NULL)
		cout<<l->data<<",";
		else
			cout<<l->data;	
	l=l->next;
	}
}
void MergeList(LinkList &La,LinkList &Lb,LinkList &Lc)//两链表合并 
{
	LinkList pa,pb,pc;
	pa=La->next;
	pb=Lb->next;
	Lc=La;//让la的头结点作为lc的头结点 
	pc=Lc; //pc初始化也指向la的头结点 
	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;//当其中一个链表结束,那么插入另外一个链表的剩余的部分 
	delete Lb;//释放Lb的头结点 
} 
int main()
{	
    LinkList La;
    LinkList Lc;
    LinkList Lb;
    InitList(La);
    InitList(Lb);
    int n;
	int m;
	cout<<"请输入在表A中添加的元素个数:";
	cin>>n; 
	CreateList(La,n);
	cout<<"请输入在表B中添加的元素个数:";
	cin>>m; 
	CreateList(Lb,m);
 	cout<<"两表合并后的表c元素依次为:"; 
	 MergeList(La,Lb,Lc);
     TraverseList_L(Lc);
} 

在这里插入图片描述

3.不重复式合并

我们也发现,我们的例子中,8,11这两个数字出现了两次,那么其实我们可以让数字不重复的合并,其实就可以把合并的代码这么改(拿顺序有序表来说)

void MergeList(SqList La,SqList Lb,SqList &Lc)
{
	Lc.length=La.length+Lb.length;
	Lc.elem=new ElemType[Lc.length];
	ElemType *pc=Lc.elem;//pc指向集合C的第一个元素 
	ElemType *pa=La.elem;//pa指向集合A的第一个元素 
	ElemType *pb=Lb.elem;//pb指向集合B的第一个元素 
	ElemType *pa_last=La.elem+La.length-1;//指向A集合的尾元素 
	ElemType *pb_last=Lb.elem+Lb.length-1;//指向B集合的尾元素 
	while((pa<=pa_last)&&(pb<=pb_last))
	{
		if(*pa<*pb)//比较两个元素大小,小的在前大的在后 
		*pc++=*pa++;//赋值的同时指针向后移动 
	     else if(*pa>*pb)
	     {
	     		*pc++=*pb++;
		 }
		else
	    {
			*pc++=*pa++;//把两者之一插入即可
			pb++;//两个表的指针都要向后移动
			Lc.length--;//对于长度需要减1
		}
	}
	while(pa<=pa_last)//谁先结束谁再次循环 
	*pc++=*pa++;
	while(pb<=pb_last)
	*pc++=*pb++;
} 

4.双递增合并一递减

我们还是拿2中的例题来说,既然A和B集合都是递增,那么我们可不可以把两个递增的集合合并成一个递减的集合,当然可以,主要思路是利用头插法,如下:

#include<stdio.h>
#include<iostream>
using namespace std; 
#define OK  1
#define ERROR 0
#define MAXSIZE 100 
typedef  int  Status;
typedef  int  ElemType;
typedef struct LNode{
	ElemType data;
	struct LNode *next;
}LNode,*LinkList;
Status InitList(LinkList &L)//初始化单链表 
{
	L=new LNode;
	L->next=NULL;
	return OK;
}
void CreateList(LinkList &L,int n)//创建顺序表函数,初始化前几个元素 
{
	LinkList p,q;
	q=L;
	for(int i=n;i>0;i--)
	{
		p=new LNode;
		cin>>p->data;
		p->next=NULL;
		q->next=p;
		q=p;
	 } 
} 
void TraverseList_L(LinkList l)//遍历集合 
{
	l=l->next;
	while(l)
	{
		if(l->next!=NULL)
		cout<<l->data<<",";
		else
			cout<<l->data;	
	l=l->next;
	}
}
void MergeList(LinkList &La,LinkList &Lb)//两链表合并 
{
	LinkList pa,pb,p;
	pa=La->next;
	pb=Lb->next; 
	La->next=NULL;
	while(pa&&pb)//两集合如果都没到最后那么进行此循环进行,按照从小到大的顺序将结点依次相连 
	{
	   	if(pa->data<=pb->data)
	   	{
	   		p=pa->next;
	   		pa->next=La->next;
			La->next=pa;
			pa=p; 
		}
		else{
			p=pb->next;
			pb->next=La->next;
			La->next=pb;
			pb=p;
		}
	}
    while(pa)
    {
    	p=pa->next;//把pa的后继暂存于p
    	pa->next=La->next;//将pa结点链接于结果表中,同时实现倒置
    	La->next=pa;
    	pa=p;
	}
	  while(pb)
    {
    	p=pb->next;
    	pb->next=La->next;
    	La->next=pb;
    	pb=p;
	}
	delete Lb;//释放Lb的头结点 
} 
int main()
{	
    LinkList La;
    LinkList Lb;
    InitList(La);
    InitList(Lb);
    int n;
	int m;
	cout<<"请输入在表A中添加的元素个数:";
	cin>>n; 
	CreateList(La,n);
	cout<<"请输入在表B中添加的元素个数:";
	cin>>m; 
	CreateList(Lb,m);
 	cout<<"两表合并后的表c元素依次为:"; 
	 MergeList(La,Lb);
     TraverseList_L(La);
} 

5.稀疏多项式的合并

比如我们有两个多项式A(x)=7+3x+9x8+5x17,B(x)=8x+22x7-9x8,要求把他们俩相加合并废话不多说,直接代码讲解:

#include<iostream>
using namespace std;
typedef struct PNode{
	float coef;//系数 
	int expn;//指数  
	struct PNode *next;
}PNode,*Polynomial;
void CreatePolyn(Polynomial &P,int n)//输入n项系数和指数,建立多项式有序链表P 
{
	Polynomial s,pre,p,q;
	P=new PNode;//建立一个带头结点的单链表 
	P->next=NULL;
	for(int i=1;i<=n;i++)
	{
		s=new PNode;//生成新的结点 
		cin>>s->coef>>s->expn;
		pre=P;//pre用于保存q的前驱,初值为头结点 
		q=P->next;//q初始化指向第一个有元素的结点 
		while(q&&q->expn<s->expn)//通过比较指数找到第一个大于输入项指数的项*q 
		{
			pre=q;
			q=q->next;
		}
		s->next=q;//把新的结点s插在q和前驱结点之间 
		pre->next=s;
	}
} 
void AddPolyn(Polynomial &pa,Polynomial &pb)//计算多项式的和 
{
	float sum; 
	Polynomial p1,p2,p3,r;
	p1=pa->next;//p1,p2分别指向第一个有元素的结点 
	p2=pb->next;
	p3=pa;//p3就是运算后的结果链表的头指针,初始值为pa 
	while(p1&&p2)//p1和p2均为非空 
	{
		if(p1->expn==p2->expn)//如果两个指数相同 
		{
			sum=p1->coef+p2->coef;//系数相加 
			if(sum!=0)
			{
				p1->coef=sum;//修改pa当前结点的系数值为两项系数之和 
				p3->next=p1;// 将修改后的pa当前结点链在p3之后,p3指向p1 
				p3=p1;
				p1=p1->next;
				r=p2;
				p2=p2->next;
				delete r;
			}
			else{
				r=p1;
				p1=p1->next;
				delete r;
				r=p2;
				p2=p2->next;
				delete r;
			}
		}
		else if(p1->expn<p2->expn)
		{
			p3->next=p1;
			p3=p1;
			p1=p1->next;
		}
		
		else{
			p3->next=p2;
			p3=p2;
			p2=p2->next;
			
		}
	} 
	p3->next=p1?p1:p2;
	delete pb;
}
void print(Polynomial L1)//依次打印各个结点的系数和指数 
{
	L1=L1->next;
	while(L1)
	{
		cout<<endl<<L1->coef<<" "<<L1->expn<<endl; 
		L1=L1->next;
	} 		
} 
int main()
{
	Polynomial L1;
	Polynomial L2;
	int n;
	int m;
	cout<<"请输入第一个链表的元素个数和各个元素的系数和指数值:";
	cin>>n; 
	CreatePolyn(L1,n);
		cout<<"请输入第一个链表的元素个数和各个元素的系数和指数值:";
	cin>>m;
	CreatePolyn(L2,m);
	AddPolyn(L1,L2);
	cout<<"------------------------运行结果为----------------------------------\n"; 
	print(L1); 	
} 

运行结果:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_45737068/article/details/106525949
今日推荐