线性表的链式表示习题

设计一个递归算法,删除不带头结点的单链表L中所有值为x的结点
void Del_x_recursion(Linklist &L,int x){
    if(L==NULL) return;
    if(L->data!=x){
        Del_x_recursion(L->next,x);
        return;
    }
    LNode *p;
    p=L;
    L=L->next;
    free(p);
    Del_x_recursion(L,x);
} 

 

在带头结点的单链表L中,删除所有值为x的结点,并释放其空间,假设值为x的结点不唯一
/**两个指针一次遍历**/
void Del_x_1(Linklist &L,int x){
    LNode *p=L->next,*pre=L,*q;
    while(p!=NULL){
        if(p->data==x){
            q=p;
            p=p->next;
            pre->next=p;
            free(q);
        }
        else{
            pre=p;
            p=p->next;
        }
    }
    
} 

 

设L为带头结点的单链表,编写算法从尾到头反向输出每个结点的值
/**借助栈来实现,每经过一个结点将值压入栈中,再从栈顶输出值即可。**/
 void R_Print(Linklist &L){
     if(L->next!=NULL)
       R_Print(L->next);  //递归
    printf(L->data); 
 }

 

 在带头结点的单链表L中删除一个最小值结点的高效算法(假设最小值结点唯一
 LinkList Del_Min(Linklist &L){
     LNode *pre=L,*p=pre->next;
     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_2(Linklist L){
     LNode *pre,*p=L->next,*r=p->next;
     p->next=NULL;  //处理第一个指针
     while(r!NULL){//r为空则说明p是最后一个结点
     pre=p;
     p=r;
     r=r->next;
     p->next=pre;//指针反转 
     } 
     L->next=p;  //处理最后一个指针
     return L; 
 } 

 

有一个带头结点的单链表L,设计算法使其元素递增有序
/**结点重排**/
void Sort(Linklist &L){
    LNode*p=L->next,*pre;
    LNode*r=p->next;  //用r保存p后继结点,以保证不断链
    p->next=NULL;
    p=r;
    while(p!=NULL){
        r=p->next;
        pre=L;
        while(pre->next!=NULL&&pre->next->data<p->data)
            pre=pre->next;
        p->next=pre->next; //把p插入pre后
        pre->next=p;
        p=r;    //扫描原单链表中剩下的结点 
    } 
} 

 

在一个带头结点的单链表中所有元素结点数据值无序,编写程序,删除表中介于给定两个值之间的元素的元素
void RangeDelete(Linklist &L,int min,int max){
    LNode *pr=L,*p=L->next;  //p为工作指针,pr是其前驱
    while(p!=NULL){
        if(p->data>min&&p->data<max){
            pr->next=p->next;
            free(p);
            p=pr->next;
        }
        else{
            pr=p;
            p=p->next;
        }
    } 
    
}

 

给定两个单链表,找出两个链表的公共结点
/**有公共结点也就是说,两个链表从某一结点开始他们的next都指向同一个结点
因为每个结点都只有一个next域**/
//思路:分别遍历找到长度,求出两个长度之差,在长的链表上先遍历长度之差个结点后再同步遍历两个表
Linklist Sesrch_lis_common(Linklist L1,Linklist L2){
    int len1=length(L1),len2=length(L2),dist;
    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;
        } 
    }
    return NULL;
} 

 

给定一个带表头结点的单链表head(data,next),试写算法按递增次序输出单链表中各结点的数据元素,
并释放结点所占的存储空间(不允许使用数组作辅助空间) 
void Min_Delete(Linklist &head){
    while(head->next!=NULL){//循环到只剩头结点 
        minpre=head;
        p=head->next;    //p工作指针
        while(p->next!=NULL){
            if(p->next->data<minpre->next->data)
               minpre=p;
            p=p->next;
        } 
        printf(minpre->next->data);
        u=minpre->next;
        minpre->next=u->next;
        free(u); 
    }
    free(head);
} 

 

将一个带头结点的单链表A分解成两个带头结点的单链表A和B
使A表中含有原表中序号为奇数的元素,B表含偶数,且保持相对顺序不变
/**设置访问序号变量**/*r尾结点指针 
Linklist DisCreate_l(Linklist &A){
    int i=0;
    Linklist B=(Linklist)malloc(sizeof(LNode));  //创建B表头
    B->next=NULL;
    LNode *ra=A,*rb=B;   //ra rb分别指向将创建的AB表尾部
    LNode *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;
} 

 

在递增有序的线性表中,有数值相同的元素存在。若存储方式为单链表,设计算法使表中不再有重复的元素
void Del_Same(Linklist &L){
    LNode *p=L->next,*q;
    if(p==NULL) return;
    while(p->next!=NULL){
        q=p->next;
        if(p->data==q->data){
            p->next=q->next;
            free(q);
        }
        else
        p=p->next;
    }
} 

 

假设有两个元素按序递增的单链表,将这两个单链表归并为一个按元素值递减次序排列的单链表,并要求
利用原来两个单链表的结点存放归并后的单链表
void MergeList(Linklist &La,Linklist &Lb){
    LNode *r,*pa=La->next,*pb=Lb->next;
    La->next=NULL;
    while(pa&&pb)//两链表均不为空时
       if(pa->data<=pb->data){
           r=pa->next;
           pa->next=La->next;
           La->next=pa;
           pa=r;
       } 
       else{
           r=pb->next;
           pb->next=La->next;
           La->next=pb;
           pb=r;
       }
    if(pa) pb=pa;
    while(pb){   //处理剩下一个非空链表,依次插入到La 
        r=pb->next;
        pb->next=La->next;
        La->next=pb;
        pb=r;
    }
    free(Lb);
} 

 

设AB两个带头结点的单链表,递增有序,从AB中公共元素产生单链表C
要求不破坏AB结点
void GetCommon(Linklist A,Linkilist B){
    LNode *p=A->next,*q=B->next,*r,*s;
    Linklist C=(Linklist)malloc(sizeof(LNode));
    r=c;  //r始终指向c表尾
    while(p!=NULL&&q!=NULL){
        if(p->data<q->data)
          p=p->next;
        else  if(p->data>q->data)
          q=q->next;
        else{
            s=(LNode*)malloc(sizeof(LNode));
            s->data=p->data;
            r->next=s;  //将*s链接到c上  尾插
            r=s;
            p=p->next;//表AB继续扫描 
            q=q->next; 
        }
    } 
    r->next=NULL;
} 

 

已知两个元素递增排列的链表AB,求AB交集并存放在A链表
Linklist Union(Linklist &la,Linklist &lb){
    pa=la->next;
    pb=lb->next;
    pc=la;      //结果表中当前合并结点的前驱指针
    while(pa&&pb){
        if(pa->data==pb->data){
            pc->next=pa;
            pc=pa;
            pa=pa->next;
            u=pb;  //B中结点释放 
            pb=pb->next;
            free(u);
            
        }
        else if(pa->data<pb->data){
            u=pa;
            pa=pa->next;
            free(u);
        }
        else{
            u=pb;
            pb=pb->next;
            free(u);
        }
    } 
    while(pa){ //A未遍历完
       u=pa;
       pa=pa->next;
       free(u); //释放A中剩余结点  
    }
    while(pb){
        u=pb;pb=pb->next;
        free(u);
    }
    pc->next=NULL;
    free(lb);
    return la;
} 

 

两个整数序列A=a1,a2..an,B=b1,b2...bn已存入两个单链表中
判断序列B是否为序列A的连续子序列
/**暴力法**/
 int Pattern(Linklist A,Linklist B){
     LNode *p=A;  //p为链表A的工作指针(假定无头结点
    LNode *pre=p;   //pre记住每趟比较中A链表的开始结点
    LNode *q=B;
    while(p&&q){
        if(p->data==q->data){
            p=p->next;
            q=q->next;
        }
        else{
            pre=pre->next;
            p=pre;
            q=B;
        }
        
    } 
    if(q=NULL)//B已经结束
       return 1;//说明是A的连续子序列
    else
      return 0; 
 }

 

 设计算法判断带头结点循环双链表是否对称
 int Symmetry(DLinklist L){
 //本算法从两头扫描循环双链表
     DNode *p=L->next,*q=L->prior;
     while(p!=q&&q->next!=p)
        if(p->data==q->data){
            p=p->next;
            q=q->prior;
        }
        else  return 0;
    return 1;    
 } 

 

有两个循环单链表,链表头指针分别为h1 h2,编写函数将链表2链接到链表1之后,
要求链接后的链表仍保持循环单链表形式
Linklist Link(Linklist &h1,Linklist &h2){
    LNode *p,*q;
    p=h1;
    while(p->next!=NULL)   //寻找h1的尾结点
        p=p->next;
    q=h2;
    while(q->next!=NULL)
        q=q->next;
    p->next=h2;    //将h2链接到h1后 
    q->next=h1;
    return h1;
} 

 

设一个带头结点的循环单链表,其结点值均为正整数
设计算法反复找出单链表结点值最小的结点并输出,然后将该结点删除,直到单链表空为止,在删除表头结点
void Del_ALL(Linklist &L){
    LNode *p,*pre,*minp,*minpre;
    while(L->next!=L){  //表不空,循环
       p=L->next;pre=L;
       minp=p;minpre=pre;
       while(P!=L){
           if(p->data<minp->data){
               minp=p;minpre=pre;
           }
           pre=p;
           p=p->next;
       } 
       printf("%d",minp->data);
       minpre->next=minp->next;
       free(minp);
   }
   free(L);
} 

 

设头指针为L的带头表头结点的非循环双向链表,其每个结点中除有pre,data,next域外,还有一个访问频度域freq。
在链表被启用前,其值均初始化为零。每当在链表中进行一次locate(L,x)运算时,令元素值为x的结点中freq域的值+1,
并使此链表中结点保持按访问频度非增(递减)的顺序排列,同时最近访问的结点排在频度相同的结点前面,以便使频繁
访问的结点总是靠近表头。试编写符合上述要求的locate(L,x)的算法,该运算为函数过程,返回找到结点的地址,类
型为指针型
DLinkist Locate(DLinklist &L,int x){
    DNode *p=L->next,*q;
    while(p&&p->data!=x)
        p=p->next;
    if(!p){
        printf("不存在值为x的结点\n");
        exit(0);
    }
    else{
        p->freq++;
        p->next->pred=p->pred;
        p->pred->next=p->next;
        q=p->pred;
        while(q!=L&&q->freq<=p->freq)
            q=q->pred;
        p->next=q->next;
        q->next->pred=p;
        p->pred=q;
        q->next=p;
    }
    return p;
} 

 

带头结点的单链表[data,link]
假设只给出头指针list,在不改变链表的前提下,设计算法查找链表中倒数第k个位置
上的结点,查找成功则输出data值,返回1,否则返回0
typedef struct LNode{
    int data;
    sttuct Lnode *link;
}*Linklist;
int Search_k(Linklist list,int k){
    Linklist p=list->link,q=list->link;
    int count=0;
    while(p!=NULL){  //遍历链表直到最后一个结点
       if(count<k)  count++;//计数,若count<k则只移动p
       else q=q->link;
         p=p->link; 
    }
    if(count<k) return 0;
    else{
        printf("%d",q->data);
        return 1;
    }
} 

 

假定采用带头结点的单链表保存单词,当两个单词有相同后缀时,则可共享相同的后缀存储空间
设str1 str2分别指向两个单词所在单链表的头结点,找出由str1 str2所指向两个链表共同后缀起始位置 
LinkNode *Find_1st_Common(LinkList str1,Linklist str2){
    int len1=length(str1),len2=length(str2);
    LinkNode *q,*p;
    for(p=str1;len1>len2;len1--){
           p=p->next;
    }
    for(q=str2;len2>len1;len2--){
          q=q->next; 
    }
    while(p->next!=q->next&&p->next!=NULL){
        p=p->next;
        q=q->next;
    }
    return p->next;
}

 

单链表保存了m个整数,结点结构为[data][link],且|data|<n(n为正整数)
设计时间复杂度高效算法,对于链表中data绝对值相等的结点,仅保留第一次出现的结点而删除其余绝对值相等的结点
 typedef struct node{
     int data;
     struct node *link;
 }NODE;
 typedef NODE *PNODE;
 void func(PNODE h,int n){
     PNODE p=h,r; 
     int *q,m;
     q=(int*)malloc(sizeof(int)*(n+1));
     for(int i=0;i<n+1;i++)
         *(q+i)=0; //数组元素初位置0  q为数组*(q+i)=q[i] 
         while(p->link!=NULL){
             m=p->link->data>0?p->link->data:-p->link->data;
             if(*(q+m)==0){
                 //判断该结点的data是否已出现 
                 *(q+m)=1;  //首次出现 
                 p=p->next;
             }
             else{
                 r=p->link;
                 //delete
                 p->link=r->link;
                 free(r);
             }
         } 
         free(q);
 }

 

posted @ 2020-04-25 23:07  iiiiiki  阅读(716)  评论(0)    收藏  举报