练习(wd Stack)

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

第一想法:我先删除试试,要删除链表部位空,遍历单链表

LinkNode *q=p->link;

p->link=q->link;

x=q->data;delete q;

【分析】递归模型:

终止条件:若L为空表,f(L,X)=不做任何事

                   若L->data==x,f(L,X)=删除结点*L;f(L->next,x);

                   其他情况,f(L,x)=f(L->next,x)

void Del_x(Linklist &L,Elemtype x){
//递归实现在单链表L上删除值为x的结点
    LNode *p;
    if(L==NULL)   //递归出口
        return;
    if(L->data==x){   //若L所指结点的值为x,删除*L,并让L指向下一结点
        p=L;
        L=L->next;
        free(p);
        Del_x(L,x);    //递归调用
}
else                    //若L所指结点的值不为x
    Del_x(L->next,x);   
}

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

第一想法:要删除,遍历单链表,每个结点的数据域与x比较,若相等则删除,否则指针后移 直到结束

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

指针pre、p同步后移一个结点

void Del_X(Linklist &L,Elemtype x){
        //L为带头结点的单链表
    LNode *p=L->next,*pre=L,*q;   //置p和pre 的初始值
    while(p!=NULL){
        if(p->data==x){
            q=p;
            p=p->next;
            pre->next=p;
            free(q);
}
    else{
        pre=p;
        p=p->next;
        }//else
    }//while
}

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

第一想法:头插法建立单链表然后输出元素,可以实现这个

【】可借助栈来实现,没经过一个结点存入栈中,遍历完整个链表在从栈顶开始输出结点值

void Print(LinkList &L){
    //从尾到头输出单链表中每个结点的值
    if(L->next!=NULL){
        Print(L->next);      //递归
    }
    printf(L->data);
}

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

第一想法:先不提高效,先实现删除最小值结点。设立一个变量temp和index,遍历单链表,挨个比较,每当有结点值小于temp,把temp的值更改为当前小的那个,index记录那个结点的指针域。

【】用p从头至尾扫描单链表,pre指向*p结点的前驱,用minp保存值最小的结点指针(初值为p),minpre指向*minp结点的前驱(初值为pre)。一边扫描,一边比较,若p->data小min->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)

第一想法:先用个数组操作下,

for(int i=0,j=len;i<j;i++,j--){

int temp =arr[i];

arr[i]=arr[j];

arr[j]=temp;

}

【】将头结点摘下,然后从第一结点开始依次插入到头结点的后面(头插法建立单链表),直到最后一个结点为止

LinkLIst Reverse(LinkList 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){
    LNode *p=L->next,*pre;
    LNode *r=p->next;    //r保持*p后继结点指针,以保证不断链
    p->next=NULL;        //构造只含一p=r;个数据结点的有序表
    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 (a,b,arr[]){

         int i;

for(i=0i>arr.length;i++){

if(arr[i]>a&&arr[i]<b)

delete;

}

}

void RangeDelete(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;
}
}

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

第一想法:最笨的方法,两个for暴力找了。或者给他俩排个序,再遍历寻找

LinkList Search_common(LinkList L1,LinkList L2){
        int len1=Length(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--)
            longList=longList->next;
         while(longList!=NULL){
            if(longList==shortList)
                return longList;
           else{
                longList=longList->next;
                shortList=shortList->next;
    }
    }//while
    return NULL;
}

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

【】对

void Min_Del(LinkList &head){
    //head是带头结点的单链表指针
    while(head->next!=NULL){
        pre=head;
        p=pre->next;        //p为工作指针
        while(p->next!=NULL){
             if(p->next->data <pre->data>data)
             pre=p;          //记住当前最小值结点的前驱结点的指针
             p=p->next;        //p为工作指针
            }
        print(pre->next->data);
        u=pre->next;            //删除元素值最小的结点,释放结点空间
        pre->next=u->next;
        free(u);
}
    free(head);
}

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

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

第一想法:新建个单链表B,遍历A如果当前值%2!=0存入B,否则指针移动到下一个直到结束

LinkList DisCreate(LinkList &A){
    i=0;
    B=(LinkList)malloc(sizeof(LNode)); //创建B表表头
    B->next=NULL;                    //B表初始化
    LNode *ra=A,*rb=B;                //ra和rb将分别指向创建的A表和B表的尾结点
    
    p=A->next;                        //p为链表工作指针,指向待分解的结点
    A->next=NULL;                     //置空新的A表
    while(p!=NULL){
        i++;
        if(i%2==0){
            rb->next=p;
            ra=p;
}
    p=p->next;
}
    ra->next=NULL;
    rb->next=NULL;
    return B;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值