List-练习(11/4)

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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值