1.设计递归算法,删除不带头结点的单链表L中所有值为x的结点
//the first method
void delet_x(LinkList &L,x){
if(L=NULL) return NULL;
while(L!=NULL){
if(L->next->data==x)
L->next=L->next->next;
}
}
//解析,简述递归解决
void Del_x(LinkList &L,elemtype x){
LNode *p; //p指向待删除结点
if(L==NULL)return;
if(L->data==x){
p=L; //删除*L,并让L指向下一结点
L=L->next;
free(p);
Del_x(L,x); //递归调用
}
else //若L所指结点值不为x
Del_x(L->next,x);
}
2.在带头结点单链表L中,删除所有值为x的结点,并释放其空间,假设值为x的结点不唯一,试编写算法实现上述操作。
//the first method
void del_x(LinkList &L,int x){
LNode *p=L->next;
if(p->next=NULL) return null;
while(p->next!=null){
if(p->next->data=x)
p->next=p->next->next;
p=p->next;
}
}
//解析
void del_x(LinkList &L,elemtype x){
LNode *p=L->next,*pre=L,*q;
while(p!=NULL){
if(p->data==x){
q=p; //q指向该结点
p=p->next;
pre->next=p;
free(p);
}
else{ //否咋同步后移
pre=p;
p=p->next;
}//else
}//while
}
3.设L为带头结点的单链表,编写算法实现从尾到头反向输出每个结点的值
//the first method
//用栈可以轻松完成,或者递归?
//我又GG了
void PrintList(LinkList &L){
LNode *p=L->next;
p->next=last;
while(last->next!=NULL) {
p=p->next;
last=lat->next;
}
}
//解析
void R_Print(LinkList L){
if(L->next!=NULL){
R_Print(L->next);
}//if
printf(L->data);
}
4.试着编写带头结点的单链表L中删除一个最小值的高效算法(假设最小值唯一)
/**初始想法:遍历链表,用min记录结点值;初始化min=第一个结点值,用index记录最小值地址,每次结点值都与min比较若min<L->data,更新min值,更新index,指针后移;否则,指针后移
**/
del min(LinkList &L,int x){
int min;
LNode *p=L->next;
LNode *index=p,*temp=L,*q=null;
if(p!=NULL) return NULL;
while(p->next!=NULL){
if(min<p->data){
index=p;
temp=temp->next;;
p=p->next;
}
q->next=index;
temp->next=temp->next->next;
free(q);
}
}
//解析
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){
min=p; //找到比此前找到的最小值更小的结点
minp=pre;
}
pre=p; //继续扫描下一个结点
p=p->next;
}
minpre->next=minp->next;
free(minp);
return L;
}
5.试着编写算法将带头结点的单链表就地逆置,所谓就地是指辅助空间复杂度为O(1)
//原地逆置单链表,写了几次,还是分分钟出错
//好像用尾插法的思想
void reverse(LinkList &L){
LNode *pre,*rear,*p;
p->next=rear;
pre=L;
}
//解析
LinkList reverse(LinkList L){
LNode *p,*r; //p为工作指针,r为p的后继,防止断链
p=L->next; //从第一个元素开始
L->next=NULL;
while(p!=NULL){ //依次将结点摘下
r=p->next; //暂存p的后继
p->next=L->next; //将p结点插入到头结点之后
L->next=p;
p=r;
}
reutrn L;
}
6.有一个带头结点的单链表L,设计一个算法使其元素递增有序
//思路;比较当前结点值与后继结点值,如p->data<p->next->data,修改元素值;否则,指针后移
void riseList(LinkList &L){
LNode *pre,*p;
p=L->next;
while(p->next->next!=NULL){
if(p->data>p->next->data){
int temp=p->data;
p->data=p->next->data;
p->next->data=temp;
p=p->next;
}
}
}
//解析
/***基本思想:插入排序,先构成一个只含一个数据结点的有序链表,然后依次扫描链表剩余的结点*p,在有序表中通过比较查找插入*p的前驱结点*pre,然后将*p插入 *pre之后 **/
void Sort(LinkList &L){
LNode *p=L->next,*pre;
LNode *r=p->next; //r保持*p后继结点指针,保证不断链
p->next=NULL; //构造只含一个结点的有序表
p=r;
while(pre->next!=NULL &&pre->next->data < p->data)
r=pre->next; // 保存*p的后继结点指针
p->next;
p->next=pre->next; //将*p插入到*pre之后
pre->next=p;
p=r; //扫描原单链表中剩下的结点
}
7.设在一个带表头结点的单链表中所有元素结点的数据值无序,时则会编写一个函数,删除表中所有介于给定的两个值(作为函数参数给出)之间的元素的元素(若存在)
//判断当前结点的值是否在区间内,若是删除,否则指针后移
void deleRange(LinkList &L,int left,int right){
LNode *p=L->next,*q=NULL;
while(P->next!=NULL){
if(p->data<left &&p->data <right){
q=p;
p->next=p->next->next;
free(q);
p=p->next;
}
}
}
解析:因为无序,所以只能逐个检查
void RangeDel(LinkList &L,int min,int max){
Lnode *pr=L,*p=L->link; //p是检测指针,pr是前驱
while(p!=NULL)
if(p->data > min && p->data<max){ //寻找到被删除结点,删除
pr->link=p->link;
free(p);
p=pr->link;
}else
{
pr=p;
p=p->link;
}
}
8.给定两个单链表,编写算法找出两个链表的公共结点
//遍历两个链表,若a->data=b->data,printf(a->data);else a=a->next,b=b->next;
//要考虑两个链表的长度不一样的情况
void findCommon(LinkList &A,LinkList &B b){
LNode *a,LNode *b;
a=A->next;
b=B->next;
while(a->next!=NULL && b->next!=NULL){
if(a->data==b->data) printf("%d",a->data);
a=a->next;
b=b->next;
}
whie(a->next==NULL&&b->next!=NULL)
a=A->next;
if(a->data==b->data) printf("%d",a->data);
printf("%d",a->data);
while(b->next==NULL&&a->next!=NULL)
b=B->next;
if(a->data==b->data) printf("%d",a->data);
printf("%d",a->data);
}
//解析
LinkList searchCommon(LinkList L1,LinkList L2){
int len1=Lengt(L1),len2=Length(L2);
LinkList longList,shortlist;
if(len1>len2){
longlist=L1->next;
shortList=L2->next;
dist=len1-len2;
}
else{
longList=L2->next;
shortList=L1->next;
dist=len2-len1;
}
while(dist--)
lonList=longList->next;
while(longList!=NULL){
if(longList==shortList) return longList;
return longList;
else{
longList=longList->next;
shortList=shortList->next;
}
} //while
return NULL;
}
9.给定一个带表头结点的单链表的,设head为头指针,结点结构为(data,next),data为整型元素,next为指针,试写出算法:
按递增次序输出单链表中各结点的数据元素,并释放结点所占的存储空间(要求:不允许使用数组作为辅助空间)
//。。。没思路,排序再输出么。。。
//解析:遍历链表,每次遍历中找出最小值元素,输出并释放结点所占空间;再次查找次小值,输出并释放空间,如此重复直到链表为空。最后释放头节点所占存储空间
void MinDelete(LinkList &head){
LNode *u;
while(head->next!=NULL){
pre=head; //pre为最小值结点的前驱结点的指针
p=pre->next; //p为工作指针
while(p->next!=NULL){
if(p->next->data <pre->next->data)
pre=p; //记住最小值前驱
p=p->next;
}
print(pre->next->data); //输出最小值
u=pre->next; //删除
pre->next=u->next;
free(u);
}
free(head);
}
10.将一个带头结点的单链表A分解为两个带头结点的单链表A和B,使得A表中含有原表中序号为奇数的元素,而B
表中序号为偶数的元素,且保持其相对顺序不变
//建立链表B,遍历A若当前结点值为偶数将该结点存入B;否则,指针后移
void Split_Even_Odd(LinkList A,LinkList B){
LNode *p=A->next,*b=B->next,*q;
while(p->next!=NULL){
if(p->data%2==0)
b->next->data=p->data;
b=b->next;
q=p;
p=p->next;
free(q);
p=p->next;
}
}
//解析
//设置访问序号变量,每访问一个结点序号加1,根据奇偶性插入A或B
LinkList disCreat(LinkList &A){
int i=0;
B=(LinkList)malloc(sizeof(LNode));
B->next=NULL;
LNode *ra=A,*rb=B;
p=A->next; //p为链表工作指针,指向待分解的结点
A->next=NULL; //置空新的A
while(p!=NULL){
i++;
if(i%2==0){ //处理偶数情况
rb->next=p;
rb=p;
}
else{
ra->next=p;
ra=p;
}
p=p->next;
}
ra->next=NULL;
rb->next=NULL;
return B;
}