/*1、假设有两个按元素值递增次序排列的线性表,均以单链表形式存储。请编写算
法将这两个单链表归并为一个按元素值递减次序排列的单链表,并要求利用原来
两个单链表的结点存放归并后的单链表。*/
List *List_merge(List *La, List *Lb)
{
List *p, *q, *r;
p = La->next; //使用p指针指向la的下一个元素
La->next = NULL; //把LA的下一个元素置为空指针
q = Lb->next; //q指针指向lb的下一个元素
while (p != NULL && q != NULL)
{
if (p->data < q->data) //头插法,结果与插入顺序相反
{
r = p->next; //使用r指针保存p指向的下一个元素指针
p->next = La->next;
La->next = p;
p = r;
}
else
{
r = q->next;
q->next = La->next;
La->next = q;
q = r;
}
}
while (p != NULL)
{
r = p->next;
p->next = La->next;
La->next = p;
p = r;
}
while (q != NULL)
{
r = q->next;
q->next = La->next;
La->next = q;
q = r;
}
return La;
}
/*2.带头结点且头指针为ha和hb的两线性表A和B 分别表示两个集合。
两表中的元素皆为递增有序。请写一算法求A和B的并集AUB。要求
该并集中的元素仍保持递增有序。且要利用A和B的原有结点空间。*/
List *merge_List(List *head1, List *head2)
{
List *La, *Lb, *r, *tail;
La = head1->next;
Lb = head2->next;
head1->next = NULL;
tail = head1;
while (La != NULL && Lb != NULL)
{
if (La->data < Lb->data)
{
r = La->next;
tail->next = La;
tail = tail->next;
La = r;
}
else if (La->data > Lb->data)
{
r = Lb->next;
tail->next = Lb;
tail = tail->next;
Lb = r;
}
else if (La->data = Lb->data) //要考虑到两个节点相等的情况,当相等时,不插入,工作指针移动到下个节点
{
r = La->next;
La = r;
}
}
while (La != NULL)
{
r = La->next;
tail->next = La;
tail = tail->next;
La = r;
}
while (Lb != NULL)
{
r = Lb->next;
tail->next = Lb;
tail = tail->next;
Lb = r;
}
return head1;
}
/*3、知L1、L2分别为两循环单链表的头结点指针,m,n分别为L1、L2
表中数据结点个数。要求设计一算法,用最快速度将两表合并成一个带
头结点的循环单链表。
思路:移动L1链表的指针到链表尾,然后将其指向L2的首元节点,而后
移动L2链表的指针到链表尾,将其指导L1的头指针即可*/
List *merge_List(List *head1, List *head2)
{
List *La, *Lb;
La = head1->next;
Lb = head2->next;
while (La->next != head1)
{
La = La->next;
}
La->next = Lb;
while (La->next != head2)
{
Lb = Lb->next;
}
Lb->next = head1;
return head1;
}
/*设计一个递归算法,删除不带头结点的单链表L中所有值为x的结点*/
//算法一(不带头结点)
void Del_X_3(Linklist &L, ElemType x)
{
LNode *p; //p指向待删除结点
if (L == NULL) //递归出口
{
return;
}
if (L->data == x)
{ //若L所指结点的值为x
p = L; //删除*L,并让L指向下一结点
L = L->next;
free(p);
Del_X_3(L, x); //递归调用
}
else //若L所指结点的值不为x
Del_X_3(L->next, x); //递归调用
}
//算法二(带头结点)
void del(LinkList &L,ElemType x){
LNode *p,*q;
p = L->next;
if(p==null){
return;
}
if(p->data==x){
q=p;
p=p->next;
free(q);
del(p,x);
}else{
del(p->next,x);
}
}
//算法三(非递归算法)
void del(LinkList &L,ElemType x){
LNode *p,*q;
p=L->next;
while(p!=null){
if(p->data==x){
q=p;//用q指针指向p指针
p=p->next;//p指针指向后继节点
free(q);//删除q节点
}else{
p=p->next;
}
}
}
/*试编写在带头结点的单链表L中删除一个最小值结点的高效算法(假设最小值结点时唯一的)*/
/*算法思想:用p从头至尾扫描单链表,pre指向*p结点的前驱,用minp保存值最小的结点指针(初值为p),
minpre指向*minp结点的前驱(初值为pre)。一边扫描,一边比较,若p->data小于minp->dara,则将p、
pre分别复制给minp、minpre。
当p扫描完毕,minp指向最小值结点,minpre指向最小值结点的前驱结点,再将minp所指结点删除即可。*/
LinkList Delete_Min(LinkList &L)
{
//L是带头结点的单链表,本算法删除其最小值结点
LNode *pre = L, *p = pre->next; //p为工作指针,pre指向其前驱
LNode *minpre = pre, *minp = p; //保存最小值结点及其前驱
while (p != NULL)
{
if (p->data < minp->data)
{
minp = p; //找到比之前找到的最小值结点更小的结点
minpre = pre;
}
pre = p; //继续扫描下一个结点
p = p->next;
}
minpre->next = minp->next; //删除最小值结点
free(minp);
return L;
}
/*试编写算法将带头结点的单链表就地逆置,所谓“就地”是指辅助空间复杂度为O(1)。*/
LinkList Reverse_1(LinkList L)
{
//L是带头结点的单链表,本算法将L就地逆置
LNode *p, *r; //p为工作指针,r为p的后继,以防断链
p - L->next; //从第一个元素结点开始
L->next = NULL; //先将头结点L的next域置为NULL
while (p != NULL)
{ //依次将元素结点摘下
r = p->next; //暂存p的后继
p->next = L->next; //将p结点插入到头结点之后
L->next = p; //
p = r; //
}
return L;
}
/*有一个带头结点的单链表L,设计一个算法使其元素递增有序。
算法思想:采用直接插入排序算法的思想,先构成只含一个数据结点
的有序单链表,然后依次扫描单链表中剩下的结点*p(直至p==NULL为止),
在有序表中通过比较查找插入*p的前驱结点*pre,然后*p插入到*pre之后,
找到合适的位置插入
*/
void Sort(LinkList &L)
{
//本算法实现将单链表L的结点重拍,使其递增有序
LNode *p = L->next, *pre;
LNode *r = p->next; //r保持*p后继结点指针,以保证不锻炼
p->next = NULL; //构造只含一个数据结点的有序表
p=r;
while (p != NULL)
{
r = p->next; //保存*p的后继结点指针
pre = L;
while (pre->next != NULL && pre->next->data < p->data)
{
pre = pre->next; //在有序表中查找插入*p的前驱结点*pre
}
p->next = pre->next; //将*p插入到*pre后
pre->next = p;
p = r; //扫描原单链表中剩下的结点
}
}
/*设在一个带头结点的单链表中所有元素结点的数据值无序,试编写一个函数,
删除表中所有介于给定的两个值(作为函数参数给出)之间的元素的元素(若存在)
因为链表是无序的,所以只能逐个节点进行检查,执行删除。
*/
void RangeDelete(LinkList &L, int min, int max)
{
LNode *pr = L, *p = L->link,*q; //p是检测指针,pr是其前驱
while (p != NULL)
{
if (p->data > min && p->data < max)
{ //寻找到被删结点,删除
q=p;
pr->link = p->link;
free(q);
p = pr->link;
}
else
{ //否则继续寻找被删结点
pr = p;
p = p->link;
}
}
}
/*设A={a1,b1,a2,b2…,an,bn}线性表,采用带头结点的la单链表存放,设计一个就地算法,将其拆分为两个线性表,使得
A={a1,a2,…,an} B={bn,…,b2,b1}
二者的差别仅在于对B表的建立不采用尾插法,而是采用头插法。
*/
LinkList DisCreat(LinkList &A)
{
LinkList B = (LinkList)malloc(sizeof(LNode)); //创建B表表头
B->next = NULL; //B表的初始化
LNode *p = A->next, *q; //p为工作指针
A->next=NULL;
LNode *ra = A; //ra始终指向A的尾结点
while (p != NULL)
{
ra->next = p;
ra = p; //将*p链到A的表尾
p = p->next;
q = p->next; //头插后,*p将断链,因此用q记忆*p的后继
p->next = B->next; //将*p插入到B的前端
B->next = p;
p = q;
}
ra->next = NULL; //A尾结点的next域置空
return B;
}
/*在一个递增有序的线性表中,有数值相同的元素存在。若存储方式为单链表,
设计算法去掉数值相同的元素,使表中不再有重复的元素。例如(7,10,10,21,30,42,42,42,51,70)将变作(7,10,21,30,42,51,70)
算法思想:由于是有序表,所有相同值域的结点都是相邻的。用p扫描递增单链表L,若*p结点的值域等于其后继结点的值域,则删除后者,否则p移向下一个结点
*/
void Del_Same(LinkList &L)
{
//L是递增有序的单链表,本算法删除表中数值相同的元素
LNode *p = L->next, *q; //p为扫描工作指针
if (p == NULL)
return;
while (p->next != NULL)
{
q = p->next; //q指向*p的后继节点
if (p->data == q->data)
{ //找到重复值的结点
p->next = q->next; //释放*q结点
free(q); //释放相同元素值的结点
}
else
p = p->next;
}
}
/*设A和B是两个单链表(带头结点),其中元素递增有序,设计一个算法从A和B中公共元素产生单链表C,要求不破坏A B 的结点
算法思想:表A ,B都有序,可从第一个元素起一次比较A、B量表的元素,若元素值不等,则值小的指针往后移,若元素值相等,
则创建一个值等于两结点的元素值的新的结点,使用尾插法插入到新的链表中,并两个原表指针后移一位,直到其中一个链表遍历到表尾。
*/
void Get_Common(LinkList A, LinkList B)
{
//本算法产生单链表A和B的公共元素的单链表的C
LNode *p = A->next, *q - B->next, *r, *s;
LinkList C = (LinkList)malloc(sizeof(LNode)); //建立表C
r = C; //r始终指向C的尾结点
while (p != NULL && q != NULL)
{ //循环挑出条件
if (p->data < q->data)
p = p->next; //若A的当前元素较小,后移指针
else if (p->data > q->data)
q = q->next; //若B的当前元素较小,后移指针
else
{ //找到公共元素结点
s = (LNode *)malloc(sizeof(LNode));
s->data = p->data; //复制产生结点*s
r->next = s; //将*s链接到C上(尾插法)
r = s;
p = p->next; //表A和表B继续向后扫描
q = q->next;
}
}
r->next = NULL; //置C尾结点指针为空
}
线性链表的一些基本算法
最新推荐文章于 2022-11-07 23:22:32 发布