(1)将两个递增的有序链表合并为一个递增的有序链表。要求结果链表仍使用原来两个链表的存储空间, 不另外占用其它的存储空间。表中不允许有重复的数据。
//合并链表La和Lb,合并后的新表使用头指针Lc指向
void MergeList(LinkList &La,LinkList &Lb,LinkList &Lc){
//pa和pb分别是链表La和Lb的工作指针,初始化为相应链表的第一个结点
pa=La->next; pb=Lb->next;
Lc=pc=La; //用La的头结点作为Lc的头结点
while(pa && pb){
//取较小者La中的元素,将pa链接在pc的后面,pa指针后移
if(pa->data < pb->data){pc->next=pa;pc=pa;pa=pa->next;}
//取较小者Lb中的元素,将pb链接在pc的后面,pb指针后移
else if(pa->data > pb->data) {pc->next=pb; pc=pb; pb=pb->next;}
//相等时取La中的元素,删除Lb中的元素
else {pc->next=pa;pc=pa;pa=pa->next;q=pb->next;delete pb ;pb =q;}
}
pc->next=pa?pa:pb; //插入剩余段
delete Lb; //释放Lb的头结点
}
(2)将两个非递减的有序链表合并为一个非递增的有序链表。要求结果链表仍使用原来两个链表的存储空间, 不另外占用其它的存储空间。表中允许有重复的数据。
//合并链表La和Lb,合并后的新表使用头指针Lc指向
void MergeList(LinkList& La, LinkList& Lb, LinkList& Lc, ) {
//pa和pb分别是链表La和Lb的工作指针,初始化为相应链表的第一个结点
pa=La->next; pb=Lb->next;
Lc=pc=La; //用La的头结点作为Lc的头结点
Lc->next=NULL;
//只要存在一个非空表,用q指向待摘取的元素
while(pa || pb ){
if(!pa) {q=pb; pb=pb->next;}//La表为空,用q指向pb,pb指针后移
else if(!pb) {q=pa; pa=pa->next;} //Lb表为空,用q指向pa,pa指针后移
//取较小者(包括相等)La中的元素,用q指向pa,pa指针后移
else if(pa->data <= pb->data) {q=pa; pa=pa->next;}
else {q=pb; pb=pb->next;}//取较小者Lb中的元素,用q指向pb,pb指针后移
q->next = Lc->next; Lc->next = q; //将q指向的结点插在Lc 表的表头结点之后
}
delete Lb; //释放Lb的头结点
}
(3)已知两个链表A和B分别表示两个集合,其元素递增排列。请设计算法求出A与B的交集,并存放于A链表中。
//只有同时出现在两集合中的元素才出现在结果表中,合并后的新表使用头指针Lc指向
void Mix(LinkList& La, LinkList& Lb, LinkList& Lc) {
pa=La->next;pb=Lb->next; //pa和pb分别是链表La和Lb的工作指针,初始化为相应链表的第一个结点
Lc=pc=La; //用La的头结点作为Lc的头结点
//交集并入结果表中
while(pa && pb) {
//从第一个结点开始进行比较,当两个链表La和Lb均为到达表尾结点时,如果两个表中相等的元素时,摘取La表中的元素,删除Lb表中的元素
if(pa->data == pb->data){ pc->next=pa;pc=pa;pa=pa->next; u=pb;pb=pb->next; delete u;}
//如果其中一个表中的元素较小时,删除此表中较小的元素,此表的工作指针后移
else if(pa->data < pb->data) {u=pa;pa=pa->next; delete u;}
//当链表La和Lb有一个到达表尾结点,为空时,依次删除另一个非空表中的所有元素。、
else {u=pb; pb=pb->next; delete u;}
}
while(pa) {u=pa; pa=pa->next; delete u;}// 释放结点空间
while(pb) {u=pb; pb=pb->next; delete u;}//释放结点空间
pc->next=null;//置链表尾标记
delete Lb; //释放Lb的头结点
}
(4)已知两个链表A和B分别表示两个集合,其元素递增排列。请设计算法求出两个集合A和B 的差集(即仅由在A中出现而不在B中出现的元素所构成的集合),并以同样的形式存储,同时返回该集合的元素个数。
//求两个集合A和B的差集是指在A中删除A和B中共有的元素,即删除链表中的相应结点,所以要保存待删除结点的前驱,使用指针pre指向前驱结点。
//差集的结果存储于单链表 La 中,*n是结果集合中元素个数,调用时为0
void Difference ( LinkList& La, LinkList& Lb,int *n ) {
pa=La->next; pb=Lb->next; //pa和pb分别是链表 La 和 Lb 的工作指针,初始化为相应链表的第一个结点
pre= La ; //pre为 La 中pa所指结点的前驱结点的指针
//从第一个结点开始进行比较,当两个链表La和Lb均为到达表尾结点时
while (pa&&pb) {
//如果La表中的元素小于Lb表中的元素,pre置为La表的工作指针pa删除Lb表中的元素
if (pa->data < pb->data){pre=pa;pa=pa->next;*n++;} //A链表中当前结点指针后移
//如果其中一个表中的元素较小时,删除此表中较小的元素,此表的工作指针后移
else if (pa->data > pb->data)pb=pb->next; //B链表中当前结点指针后移
//当链表La和Lb有一个为空时,依次删除另一个非空表中的所有元素
else {pre->next=pa->next; LinkList u=pre; pa=pa->next; delete u;}
}
}
(5)设计算法将一个带头结点的单链表A分解为两个具有相同结构的链表B、C,其中B表的结点为A表中值小于零的结点,而C表的结点为A表中值大于零的结点(链表A中的元素为非零整数,要求B、C表利用A表的结点)。
void Resolve(Linklist &La, Linklist &Lb){
//pa和pb分别是链表 La 和 Lb 的工作指针,初始化为相应链表的第一个结点
pa=La->next; pb=Lb->next;
pre= La ; //pre为 La 中pa所指结点的前驱结点的指针
while (pa){
if (pa->date < 0){
Linklist p = new Lnode;
p = pa; //生成新节点
pre->next = pa->next; //删除小于0的节点,pre始终为pa的前驱
pa = pa->next; //pa后移
p->next = NULL; //后插法将元素插入Lb中
pb->next = p;
pb = p; //插入
}
//大于0
else {
pre = pa;
pa = pa->next; //pre为pa的前驱,pa指针后移动。
}
}
}
(6)设计一个算法,通过一趟遍历在单链表中确定值最大的结点。
int GetMax(LinkList L){
if(L->next == NULL)
return NULL;
pmax = L->next;//假定第一个结点中数据具有最大值
p = L->next->next;
while (p){//如果下一个结点存在
if(p->data > pmax->data)
pmax = p; //如果p的值大于pmax的值,则重新赋值
p = p->next;//遍历链表
}
return pmax->data;
}
(7)设计一个算法,通过遍历一趟,将链表中所有结点的链接方向逆转,仍利用原表的存储空间。
void reverse(Linklist& L){
Linklist q,p=L->next;//p为第一个结点
L -> next = NULL;//第一个结点后继置空
while (p){
q = p->next;//q为p后一结点,和p同样会后移
p->next = L->next;//p结点后继改为头结点的后继,刚开始为NULL,之后都是有结点的
L->next = p;//头结点后继变为p结点,最先的是1结点,后面依次为 2 3 4 5
p = q;//p结点后移
}
}
(8)设计一个算法,删除递增有序链表中值大于mink且小于maxk的所有元素(mink和maxk是给定的两个参数,其值可以和表中的元素相同,也可以不同 )。
void Delete(Linklist &L, int mink, int maxk){
Linklist pre = L;
Linklist p = L->next;
while (p){
if (p->date > mink && p->date < maxk){
pre->next = p->next;
} //pre为pa前驱,删除不符合的节点
else{pre = pa;}//如果符合条件,使pre为pa的前驱。
p = p->next; //指向下一个节点。
}
}
(9)已知p指向双向循环链表中的一个结点,其结点结构为data、prior、next三个域,写出算法change(p)
,交换p所指向的结点和它的前缀结点的顺序。
//p是双向循环链表中的一个结点,本算法将p所指结点与其前驱结点交换。
void Change(LinkList p){
DLnode *q;
q = p->prior; // p的前驱q
q->prior->next = p; // p的前驱的前驱之后继为p
p->prior = q->prior; // p的前驱指向其前驱的前驱。
q->next = p->next; // p的前驱的后继为p的后继。
p->next->prior = q; // p的后继的前驱指向原p的前驱
q->prior = p; // p与其前驱交换
p->next = q; // p的后继指向其原来的前驱
}
(10)已知长度为n的线性表A采用顺序存储结构,请写一时间复杂度为O(n)、空间复杂度为O(1)的算法,该算法删除线性表中所有值为item的数据元素。
//删除值为item的元素(过滤遍历),顺序表的结构类型为SqList
void ListDelete(SqList &L,int item){
int j = 0;
for(int i=0; i<L.length;i++){
//如果不等于就按顺序排下去,等于就不执行
if(L.elem[i] != item){
L.elem[j] = L.elem[i];
j++;
}
}
L.length = j;
}