练习(8-16)

一、设计一个递归算法,删除不带头结点的单链表L中所有值为x的结点

void Del_x(Linklist &L,int x ){
    LNode *p;        //p指向待删除结点
    if(L=NULL) return;
    if(L->data!=x){
        Del_x(L->next,x);//递归调用
        return;

    if(L->data==x){    //若L所指结点值为x
    LNode *p;        //p指向待删除结点
    p=L;
    L=L->next;
    delete p;
    Del_x(L->next,x);  
}
    else
         Del_x(L->next,x);
}

二、在带头结点的单链表L中,删除所有值为x的结点,并释放其空间,假设值为x的结点不唯一,试编写算法实现以上操作

思路:用p从头到尾扫描单链表,pre指向*p结点的前驱。若p所指结点的值为x,则删除,并让p移向下一个结点,否则让pre、p指针同步后移一个结点

void Del_x(linklist &L,ElemType x){
    LNode *P=L->next,pre*=L,*q;
    while(p!=NULL){
         if(p->data==x){
            q=p;
            p=p->next;
            pre->next=p;  //删除*q结点
            free(q);
}
        else{
            pre=q;
            p=p->next;
}
}
}

三、设L为带头结点的单链表,编写算法实现从尾到头反向输出反向输出每个结点的值

void R_Print(LInkList L){
    if(L->next!=NULL){
      R_Print();
}
    print(L->data);
}

四、试着编写在带头结点的单链表L中删除一个最小值结点的高效算法(假设最小值结点是唯一的)

用p从头到尾扫描单链表,pre指向*p结点的前驱,用minp保存值最小的结点指针(初值尾p),minpre指向*,minp结点的前驱(初值尾pre)。一边扫描,一边比较,若p->data小于minp->data,则将p、pre分别赋值给minp,minpre。当p扫描完毕,minp指向最小值结点,minpre指向最小值结点的前驱结点,再将minp所指结点删除即可

LinkList Delete_min(LinkList &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(LinkList){
    LNode *p,*r;
    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){
        LNode *p=L->next,*pre;
        LNode *r=p->nnext;    //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 RandgeDelete (LinkList &L,int min,int max){
        LNode *pr=L,*p=L->link;
        while(p!=NULL)
            if(p->data > min && p->data <max){ //寻找到被删除结点
                pr->link=p->link;
                free(q);
                p=pr->link;
    }
    else{
        pre=p;
        p=p->link;
}
}

八、给定两个单链表,编写算法找出两个链表的公共结点

 两个单链表有公共结点,也就是说两个链表从某一个结点开始,他们的next都指向同一个结点,由于每个单链表接待你只有一个next域,因此从第一个公共结点开始,之后他们所有的结点都是重合的,不会出现分叉

若两个链表有一个公共结点,则该公共结点之后所有结点都是重合的即他们的最后一个结点必然重合。因此课通过尾结点是否相同。

在遍历到尾结点时,不能保证两个链表上同时到达尾结点。这是因为两个链表长度不一样。但假设一个链表比另一个长k个结点,我们先在长的链表遍历k个结点,之后再同步遍历,此时保证同时到达最后一个结点。

由于两个链表从第一个公共结点开始到链表的尾结点,这一部分时重合的,因此他们肯定时同时到达第一公共结点的。

总体流程为,分别遍历连个链表,并求出两个长度之差。在长的链表上先遍历长度之差个结点后,在同步遍历两个链表,直到找到相同的结点,或者一直到链表结束。

LinkList Search_common(LinkList L1,LinkList L2){
    int len1=Length(L1),len2=Length(L2);
    LinkList lonList,shortList;
    if(len1>len2){//L1较长
        lonList=L1->next;
        shortList=L2->next;
        dist=len1-len2;
}
    else{     //L2较长
        lonList=L2->next;
        shortList=L1->next;
         dist=len2-len1;
}
    while(dist--)
        //表长的链表到第dist个结点,然后同步
    longList=longList->next;
    while(longList!=NULL){         //同步寻找公共结点
        if(longList==shortList)    //找到第一个公共结点
            return longList;
        else{                    //继续同步寻找
            longList=longList->next;
            shortList=shortList->next;
}
}
return NULL;
}

 九、给定一个带表头结点的单链表,设head为头指针,结点结构为(data,next)data为整型元素,next为指针,试着写出算法:按递增次序输出单链表中各结点的数据元素,并释放结点所占的存储空间(不得使用数组作为辅助空间)

思路:对链表进行遍历在每次遍历中找出整个链表的最小值元素,输出并释放结点所占空间;再查找次小值元素,输出并释放空间。,如此重复直到链表为空,最后释放头结点所占存储空间。

void Min_Delete(LinkList &head){
    while(head->next!=NULL){
        pre=head;
        p=pre->next;
        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);
}

 

十、将一个带头结点的单链表A分解为两个带头结点的单链表A和B,使得A表含有元表序号为奇数的元素,而B表中含有原表中序号为偶数的元素,且保持其相对顺序不变。

思路:设置一个访问序号变量(初值为0), 每访问一个结点序号自动加1,然后根据序号的奇偶性将结点擦汗如到A或B中。重复上述操作直到表尾

LinkList DiscCreate(Link &A){
    i=0;
    B=(LinkList)malloc(sizeof(LNode));
    B->next=NULL;
    LNode *ra=A,*rb=B;
    p=A->next;
    A->next=NULL;
    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;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值