线性表学习笔记之链表
原创博文,转载请注明 出处
链表分类:单链表,插入删除和查找的时间复杂度均为O(n)
双链表,插入、删除和查找的时间复杂度为O(1)
循环链表,表中最后一个节点的指针不是NULL,而改为指向头结点,从而整个链表形成一个环。
静态链表,借助数组来描述线性表的链式存储结构,这儿的指针是结点的相对地址。和顺序表一样需要预先分配一块连续的内存空间。以next==0作为其结束的标志。
综合应用:
1.设计一个递归算法,删除不带头节点的单链表L中所有值为x的节点。
思路:可以设计一个函数f(L,x)删除以L为首结点指针的单链表中所有值为x的结点,那么f(L->next,x)则是删除以L->next为首结点指针的单链表中所有值等于x的结点。
借助一个递归工作栈,深度为O(n),时间复杂度为O(n)
 
        
          void Del_x(Linklist &L, ElemType x){
          
           LNode *p; //p指向待删除结点
          
          
           if(L==NULL)
          
           return;
          
           if(L->data==x){
          
           p=L;
          
           L=L->next;
          
           free(p);
          
           Del_x(L, x); 
          
           } 
          
           else
          
           Del_x(L->next, x); 
          
          }
        
            
               1
            
            
              void
            
             Del_x(Linklist &
            
              L, ElemType x){
            
            
               2
            
                   LNode *p;   
            
              //
            
            
              p指向待删除结点
            
            
               3
            
            
               4
            
            
              if
            
            (L==
            
              NULL)
            
            
               5
            
            
              return
            
            
              ;
            
            
               6
            
            
              if
            
            (L->data==
            
              x){
            
            
               7
            
                         p=
            
              L;
            
            
               8
            
                         L=L->
            
              next;
            
            
               9
            
            
                          free(p);
            
            
              10
            
            
                          Del_x(L, x);    
            
            
              11
            
            
                  }           
            
            
              12
            
            
              else
            
            
              13
            
                        Del_x(L->
            
              next, x);       
            
            
              14
            
             }
          
          
        2. 设L为带头结点 的单链表,编写算法实现从尾到头反向输出每个结点的值。
思路:方法一、将链表逆置,改变链表的方向。
方法二、借助一个栈,将结点放入栈中。在遍历完整个链表后,再从栈顶开始输出结点值。
方法三、使用递归,当访问一个结点时,先递归输出它后面的结点,再输出该结点自身。实现如下
 
        
          
            void
          
          
             R_Print(LinkList L){
          
          
            2
          
          
            if
          
          (L->next!=
          
            NULL){
          
          
            3
          
                         R_Print(L->
          
            next)
          
          
            4
          
          
                }
          
          
            5
          
                  print(L->
          
            next)
          
          
            6
          
           }
        
        
            
              1
            
            
              void
            
            
               R_Print(LinkList L){
            
            
              2
            
            
              if
            
            (L->next!=
            
              NULL){
            
            
              3
            
                           R_Print(L->
            
              next)
            
            
              4
            
            
                  }
            
            
              5
            
                    print(L->
            
              next)
            
            
              6
            
             }
          
        3.试编写在带头结点的单链表L中删除一个最小值结点的高效算法(假设最小值结点唯一)
 
        
          LinkList Delete_Min(LinkList &L){
          
           LNode *pre=L, *p=L->next; //p为工作指针,pre指向其前驱
          
           LNode *minpre=pre, *minp=p;
          
          
           while(p!=NULL){
          
           if(p->data<minpre->data){
          
           minp=p;
          
           minpre=pre;
          
           } 
          
           pre=p;
          
           p=p->next;
          
           }
          
           minpre->next=minp->next;
          
           free(minp);
          
           return L;
          
          }
        
            
               1
            
             LinkList Delete_Min(LinkList &
            
              L){
            
            
               2
            
                      LNode *pre=L, *p=L->next; 
            
              //
            
            
              p为工作指针,pre指向其前驱
            
            
               3
            
                      LNode *minpre=pre, *minp=
            
              p;
            
            
               4
            
            
               5
            
            
              while
            
            (p!=
            
              NULL){
            
            
               6
            
            
              if
            
            (p->data<minpre->
            
              data){
            
            
               7
            
                                       minp=
            
              p;
            
            
               8
            
                                       minpre=
            
              pre;
            
            
               9
            
            
                      }  
            
            
              10
            
                            pre=
            
              p;
            
            
              11
            
                            p=p->
            
              next;
            
            
              12
            
            
                  }
            
            
              13
            
                 minpre->next=minp->
            
              next;
            
            
              14
            
            
                  free(minp);
            
            
              15
            
            
              return
            
            
               L;
            
            
              16
            
             }    
          
          
        4.编写算法将带头结点的单链表就地逆置,就地指辅助空间为O(1)
方法一:将头结点摘下,然后从第一结点开始,依次前插入到头节点后面(头插法建立链表),直到最后一个节点为止。
 
        
          LinkList Reverse(LinkList &L){
          
           p=L->next;
          
           L->next=NULL;
          
           while(p!=NULL){
          
           r=p->next;
          
           p->next=L->next;
          
           L->next=p;
          
           p=r;
          
           }
          
           return L;
          
          }
        
            
               1
            
             LinkList Reverse(LinkList &
            
              L){
            
            
               2
            
                        p=L->
            
              next;
            
            
               3
            
                        L->next=
            
              NULL;
            
            
               4
            
            
              while
            
            (p!=
            
              NULL){
            
            
               5
            
                               r=p->
            
              next;
            
            
               6
            
                               p->next=L->
            
              next;
            
            
               7
            
                               L->next=
            
              p;
            
            
               8
            
                               p=
            
              r;
            
            
               9
            
            
                   }
            
            
              10
            
            
              return
            
            
               L;
            
            
              11
            
             }
          
          
        方法二:将结点的next域指向前驱结点。在处理完最后一个结点时,需要将头结点的指针指向它。时间复杂度均为O(n)
 
        
          LinkList Reverse(LinkList &L){
          
           LNode *pre,*p=L->next,*r=p->next;
          
           p->next=NULL;
          
           while(r!=NULL){
          
           pre=p;
          
           p=r;
          
           r=r->next;
          
           p->next=pre;
          
           }
          
           L->next=p;
          
           return L;
          
          }
        
            
               1
            
             LinkList Reverse(LinkList &
            
              L){
            
            
               2
            
                          LNode *pre,*p=L->next,*r=p->
            
              next;
            
            
               3
            
                          p->next=
            
              NULL;
            
            
               4
            
            
              while
            
            (r!=
            
              NULL){
            
            
               5
            
                          pre=
            
              p;
            
            
               6
            
                          p=
            
              r;
            
            
               7
            
                          r=r->
            
              next;
            
            
               8
            
                          p->next=
            
              pre;
            
            
               9
            
            
                  }
            
            
              10
            
                         L->next=
            
              p;
            
            
              11
            
            
              return
            
            
               L;
            
            
              12
            
             }
          
          
        5. 有一个带头结点的单链表L,设计一个算法使其元素递增有序。
思路:采用直接插入排序的算法,先构成只含一个数据结点的有序单链表,然后依次扫描单链表中剩下的结点*p。
 
        
          void Sort(LinkList &L){
          
           LNode *p=L->next, *pre
          
           LNode *r=p->next;
          
           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;
          
           pre->next=p;
          
           p=r;
          
           }
        
}
            
               1
            
            
              void
            
             Sort(LinkList &
            
              L){
            
            
               2
            
                     LNode *p=L->next, *
            
              pre
            
            
               3
            
                     LNode *r=p->
            
              next;
            
            
               4
            
                     p->next=
            
              NULL;
            
            
               5
            
                     p=
            
              r;
            
            
               6
            
            
              while
            
            (p!=
            
              NULL){
            
            
               7
            
                             r=p->
            
              next;
            
            
               8
            
                             pre=
            
              L;
            
            
               9
            
            
              while
            
            (pre->next!=NULL&&pre->next->data<p->
            
              data)
            
            
              10
            
                                      pre=pre->
            
              next;
            
            
              11
            
                            p->next=pre->
            
              next;
            
            
              12
            
                            pre->next=
            
              p;
            
            
              13
            
                            p=
            
              r;
            
            
              14
            
            
                  }
            
            
              15
            
            
              16
            
             }
          
          
        6.在单链表L中删除p所指结点,能够实现在O(1)的时间内删除该结点?
思路:传统的做法需要顺序查找删除结点的前驱结点,再修改链接。但是时间复杂度为O(n)。由于我们知道该结点的下一结点P->next,所以我们只需要将下一结点的数据复制到该结点,然后删除它的下一结点。如果该结点位于链表尾部 即P=NULL,这时候我们需要从链表的头结点开始顺序遍历给定节点的前驱结点,这时虽然时间复杂度为O(n),但在平均情况下,仍为O(1)。
7.给定两个单链表,编写算法找出两个链表的公共结点。
思路:比较麻烦的做法就是在第一个链表上顺序遍历每个节点,每遍历一个结点都要在第二个链表上顺序遍历所有结点。找到两个相同的结点,该算法时间复杂度为O(len1*len2)。
由于每个单链表结点只有一个next域,因此从第一个公共结点开始,之后所有的结点都是重合的,拓扑形状看起来像Y,而不是X。但是,两个链表有可能不一样长,所以我们需要截取长链表多余的部分。
 
        
          LinkList Search_Common(LinkList &L1,LinkList &L2){
          
           int len1=Length(L1),len2=Length(L2);
          
           LinkList longList,shorList;
          
           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;
          
          }
        
            
               1
            
             LinkList Search_Common(LinkList &L1,LinkList &
            
              L2){
            
            
               2
            
            
              int
            
             len1=Length(L1),len2=
            
              Length(L2);
            
            
               3
            
            
                         LinkList longList,shorList;
            
            
               4
            
            
              if
            
            (len1>
            
              len2){
            
            
               5
            
                             longList=L1->next;shortList=L2->
            
              next;
            
            
               6
            
                             dist=len1-
            
              len2;
            
            
               7
            
            
                  }
            
            
               8
            
            
              else
            
            
              {
            
            
               9
            
                             longList=L2->next,shortList=L1->
            
              next;
            
            
              10
            
                             dist=len2-
            
              len1;
            
            
              11
            
            
                  }
            
            
              12
            
            
              while
            
            (dist--
            
              )
            
            
              13
            
                            longList=longList->
            
              next
            
            
              14
            
            
              while
            
            (longList!=
            
              NULL){
            
            
              15
            
            
              if
            
            (longList==
            
              shortList)
            
            
              16
            
            
              return
            
            
               longList;
            
            
              17
            
            
              else
            
            
              {
            
            
              18
            
                         longList=longList->
            
              next;
            
            
              19
            
                         shortList=shortList->
            
              next;
            
            
              20
            
            
                       }
            
            
              21
            
            
                  }
            
            
              22
            
            
              return
            
            
               NULL;
            
            
              23
            
             }
          
          
        8.设C={a1,b1,a2,b2,...,an,bn}为线性表,采用带头结点的hc单链表存放,设计一个就地算法,将其拆分为两个线性表,使得A={a1,a2,...,an}, B={bn,...,b2,b1}.
思路:采用头插法新建B表,而A表则使用尾插法。
 
        
          LinkList DisCreat(LinkList &A){
          
           LinkList B=(LinkList)malloc(sizeof(LNode))
          
           B->next=NULL;
          
           LNode *p=A->next;
          
           LNode *ra=A; //ra始终指向A的尾结点
          
           while(p!=NULL){
          
           ra->next=p;
          
           ra=p;
          
           p=p->next;
          
           q=p->next;
          
           p->next=B->next; 
          
           B->next=p;
          
           p=q;
          
           } 
          
           ra->next=NULL;
          
           return B;
          
          }
        
            
               1
            
             LinkList DisCreat(LinkList &
            
              A){
            
            
               2
            
                      LinkList B=(LinkList)malloc(
            
              sizeof
            
            
              (LNode))
            
            
               3
            
                      B->next=
            
              NULL;
            
            
               4
            
                      LNode *p=A->
            
              next;
            
            
               5
            
                      LNode *ra=A;   
            
              //
            
            
              ra始终指向A的尾结点
            
            
               6
            
            
              while
            
            (p!=
            
              NULL){
            
            
               7
            
                              ra->next=
            
              p;
            
            
               8
            
                              ra=
            
              p;
            
            
               9
            
                              p=p->
            
              next;
            
            
              10
            
                              q=p->
            
              next;
            
            
              11
            
                              p->next=B->
            
              next; 
            
            
              12
            
                              B->next=
            
              p;
            
            
              13
            
                              p=
            
              q;
            
            
              14
            
            
                  }  
            
            
              15
            
                     ra->next=
            
              NULL;
            
            
              16
            
            
              return
            
            
               B;
            
            
              17
            
             }
          
          
        9.假设有两个按元素值递增次序排列的线性表,均以单链形式存储。请编写算法将这两个链表归并为一个按元素值递减的单链表,并要求利用原来两个单链表的结点存放归并后的链表。
思路:由于两个链表均是递增的,将其合并时,从第一个结点起进行比较,将小的结点存入链表中,同时后移工作指针。由于要求链表元素递减,故采用头插法。
 
        
          void MergeList(LinkList &A,LinkList &B){
          
           LNode *pa=A->next, *pb=B->next, *r;
          
           A->next=NULL;
          
           while(pa&&pb){
          
           if(pa->data<pb->data){
          
           r=pa->next;
          
           pa->next=A->next;
          
           A->next=pa; 
          
           pa=r;
          
           }
          
           else{
          
           r=pb->next;
          
           pb->next=A->next;
          
           A->next=pb;
          
           pb=r;
          
           }
          
           }
          
           if(pa)
          
           pb=pa;
          
           while(pb){
          
           r=pb->next;
          
           pb->next=A->next;
          
           A->next=pb;
          
           pb=r;
          
           }
          
          }
        
            
               1
            
            
              void
            
             MergeList(LinkList &A,LinkList &
            
              B){
            
            
               2
            
                         LNode *pa=A->next, *pb=B->next, *
            
              r;
            
            
               3
            
                         A->next=
            
              NULL;
            
            
               4
            
            
              while
            
            (pa&&
            
              pb){
            
            
               5
            
            
              if
            
            (pa->data<pb->
            
              data){
            
            
               6
            
                                          r=pa->
            
              next;
            
            
               7
            
                                          pa->next=A->
            
              next;
            
            
               8
            
                                          A->next=
            
              pa; 
            
            
               9
            
                                          pa=
            
              r;
            
            
              10
            
            
                                  }
            
            
              11
            
            
              else
            
            
              {
            
            
              12
            
                                         r=pb->
            
              next;
            
            
              13
            
                                         pb->next=A->
            
              next;
            
            
              14
            
                                         A->next=
            
              pb;
            
            
              15
            
                                         pb=
            
              r;
            
            
              16
            
            
                                  }
            
            
              17
            
            
                        }
            
            
              18
            
            
              if
            
            
              (pa)
            
            
              19
            
                          pb=
            
              pa;
            
            
              20
            
            
              while
            
            
              (pb){
            
            
              21
            
                           r=pb->
            
              next;
            
            
              22
            
                           pb->next=A->
            
              next;
            
            
              23
            
                           A->next=
            
              pb;
            
            
              24
            
                           pb=
            
              r;
            
            
              25
            
            
                    }
            
            
              26
            
             }    
          
          
        10.设A和B 是两个单链表带头结点,其中元素递增有序。设计一个算法从A和B中公共元素产生链表C,要求不破坏A和B的结点。
思路:尾插法新建链表C ,要求不破坏A和B的结点,所以才有比较复制的方法。
 
        
          void Get_Common(LinkList &A , LinkList &B){
          
           LNode *p=A->next, *q=B->next, *r, *s;
          
           LinkList C =(LinkList)malloc(sizeof(LNode));
          
           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=q->data;
          
           r->next=s;
          
           r=s;
          
           p=p->next;
          
           q=q->next;
          
           }
          
           }
          
           r->next=NULL;
          
          }
        
            
               1
            
            
              void
            
             Get_Common(LinkList &A , LinkList &
            
              B){
            
            
               2
            
                          LNode *p=A->next, *q=B->next, *r, *
            
              s;
            
            
               3
            
                         LinkList C =(LinkList)malloc(
            
              sizeof
            
            
              (LNode));
            
            
               4
            
                         r=
            
              C;
            
            
               5
            
            
              while
            
            (p!=NULL&&q!=
            
              NULL){
            
            
               6
            
            
              if
            
            (p->data<q->
            
              data)
            
            
               7
            
                                     p=p->
            
              next;
            
            
               8
            
            
              else
            
            
              if
            
            (p->data>q->
            
              data)
            
            
               9
            
                                     q=q->
            
              next;
            
            
              10
            
            
              else
            
            
              {
            
            
              11
            
                               s=(LNode *)malloc(
            
              sizeof
            
            
              (LNode));
            
            
              12
            
                               s->data=q->
            
              data;
            
            
              13
            
                               r->next=
            
              s;
            
            
              14
            
                               r=
            
              s;
            
            
              15
            
                              p=p->
            
              next;
            
            
              16
            
                              q=q->
            
              next;
            
            
              17
            
            
                          }
            
            
              18
            
            
                  }
            
            
              19
            
                 r->next=
            
              NULL;
            
            
              20
            
             }
          
          
        11. 已知两个链表A和B分别表示两个集合,其元素递增有序。编制函数,求A与B的交集,并存放于A的链表中。
思路:采用归并思想,设置两个工作指针pa和pb,对两个链表进行扫描,当同时出现在两集合中的元素才链接到结果表中,且仅保留一个,其他的结点全部释放。
当一个链表遍历结束后,释放另一个表剩下的全部结点。
 
        
          LinkList Union(LinkList &A , LinkList &B){
          
           pa=A->next;
          
           pb=B->next;
          
           pc=A;
          
           LNode *u;
          
           while(pa&&pb){
          
           if(pa->data==pb->data){
          
           pc->next=pa;
          
           pc=pa;
          
           pa=pa->next;
          
           u=pb;
          
           pb=pb->next;
          
           free(u);
          
           }
          
           else if(pa->data>pb->data){
          
           u=pb;
          
           pb=pb->next;
          
           free(u);
          
           }
          
           else{
          
           u=pa;
          
           pa=pa->next;
          
           free(u)
          
           }
          
           while(pa){
          
           u=pa
          
           pa=pa->next;
          
           free(u)
          
           }
          
           while(pb){
          
           u=pb
          
           pa=pb->next;
          
           free(u) 
          
           }
          
           pc->next-NULL;
          
           free(B);
          
           return A;
          
           }
          
          }
        
            
               1
            
             LinkList Union(LinkList &A , LinkList &
            
              B){
            
            
               2
            
                       pa=A->
            
              next;
            
            
               3
            
                       pb=B->
            
              next;
            
            
               4
            
                       pc=
            
              A;
            
            
               5
            
                       LNode *
            
              u;
            
            
               6
            
            
              while
            
            (pa&&
            
              pb){
            
            
               7
            
            
              if
            
            (pa->data==pb->
            
              data){
            
            
               8
            
                                    pc->next=
            
              pa;
            
            
               9
            
                                    pc=
            
              pa;
            
            
              10
            
                                    pa=pa->
            
              next;
            
            
              11
            
                                    u=
            
              pb;
            
            
              12
            
                                    pb=pb->
            
              next;
            
            
              13
            
            
                                     free(u);
            
            
              14
            
            
                         }
            
            
              15
            
            
              else
            
            
              if
            
            (pa->data>pb->
            
              data){
            
            
              16
            
                                 u=
            
              pb;
            
            
              17
            
                                 pb=pb->
            
              next;
            
            
              18
            
            
                                  free(u);
            
            
              19
            
            
                       }
            
            
              20
            
            
              else
            
            
              {
            
            
              21
            
                              u=
            
              pa;
            
            
              22
            
                              pa=pa->
            
              next;
            
            
              23
            
            
                               free(u)
            
            
              24
            
            
                      }
            
            
              25
            
            
              while
            
            
              (pa){
            
            
              26
            
                             u=
            
              pa
            
            
              27
            
                             pa=pa->
            
              next;
            
            
              28
            
            
                              free(u)
            
            
              29
            
            
                       }
            
            
              30
            
            
              while
            
            
              (pb){
            
            
              31
            
                             u=
            
              pb
            
            
              32
            
                             pa=pb->
            
              next;
            
            
              33
            
            
                              free(u) 
            
            
              34
            
            
                       }
            
            
              35
            
                    pc->next-
            
              NULL;
            
            
              36
            
            
                     free(B);
            
            
              37
            
            
              return
            
            
               A;
            
            
              38
            
            
                  }
            
            
              39
            
             }
          
          
        12.设计一个算法用于判断带头结点的循环双链表是否对称。
思路:让P从左向右扫描,q从右向左扫描。直到它们指向同一结点(结点个数为奇数时)或相邻(结点个数为偶数时)为止,若它们所指结点值相同,则继续进行下去,否则返回0,若比较全部相同则返回1。
 
        
          int Symmetry(DLinkList L){
          
           DNode *p=L->next, *q=L->prior;
          
           while(p!=q&&p->next!=q)
          
           if(p->data==q->data){
          
           p=p->next;
          
           q=q->prior;
          
           }
          
           else
          
           return 0;
          
           return 1;
          
          }
        
            
               1
            
            
              int
            
            
               Symmetry(DLinkList L){
            
            
               2
            
                       DNode *p=L->next, *q=L->
            
              prior;
            
            
               3
            
            
              while
            
            (p!=q&&p->next!=
            
              q)
            
            
               4
            
            
              if
            
            (p->data==q->
            
              data){
            
            
               5
            
                                  p=p->
            
              next;
            
            
               6
            
                                  q=q->
            
              prior;
            
            
               7
            
            
                               }
            
            
               8
            
            
              else
            
            
               9
            
            
              return
            
            
              0
            
            
              ;
            
            
              10
            
            
              return
            
            
              1
            
            
              ;
            
            
              11
            
             }
          
          
        13. 设有一个带头结点的循环单链表,其结点值均为正整数。设计一个算法,反复找出单链表中结点值最小的结点并输出,然后将该结点从中删除,直到单链表空为止,再删除表头结点。
 
        
          void Del_All(LinkList &L){
          
           LNode *p, *pre, *minp, *minpre;
          
           while(L->next!=L){
          
           p=L->next;pre=L;
          
           minp=p,minpre=L;
          
           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);
          
           Del_All(L)
          
           }
          
           free(L);
          
          }
        
            
               1
            
            
              void
            
             Del_All(LinkList &
            
              L){
            
            
               2
            
                       LNode *p, *pre, *minp, *
            
              minpre;
            
            
               3
            
            
              while
            
            (L->next!=
            
              L){
            
            
               4
            
                              p=L->next;pre=
            
              L;
            
            
               5
            
                              minp=p,minpre=
            
              L;
            
            
               6
            
            
              while
            
            (p!=
            
              L){
            
            
               7
            
            
              if
            
            (p->data<minp->data){minp=p;minpre=
            
              pre;}
            
            
               8
            
                                    pre=
            
              p;
            
            
               9
            
                                    p=p->
            
              next;
            
            
              10
            
            
                             }
            
            
              11
            
                            printf(
            
              "
            
            
              %d
            
            
              "
            
            ,minp->
            
              data);
            
            
              12
            
                            minpre->next=minp->
            
              next;
            
            
              13
            
            
                             free(minp);
            
            
              14
            
            
                             Del_All(L)
            
            
              15
            
            
                  }
            
            
              16
            
            
                       free(L);
            
            
              17
            
             }   
          
          
        14. 已知一个带有表头结点的单链表,假设该链表只给出了头指针list。在不改变链表的前提下,请设计一个尽可能高效的算法,查找链表中倒数第K个位置上的结点。若查找成功,算法输出该结点的data域的值,否则,只返回0。
设计思想:定义两个指针变量p和q,初始时均指向头结点的下一个结点,即链表的第一个结点。p指针沿链表移动;当p指针移动到第k个结点时,q指针开始于p指针同步移动;当p指针移动到最后一个结点时,q指针所指示的结点为倒数第k个结点。
 
        
          typedef int ElemType;
          
           typedef struct LNode{
          
           ElemType data;
          
           struct LNode *next;
          
           }LNode, *LinkList;
        
          int Search(LinkList L, int k){
          
           LNode *p=L->next, *q=L->next;
          
           int count=0;
          
           while(p!=NULL){
          
           if(count<k)count ++;
          
           else q=q->next;
          
           p=p->next;
          
           }
          
           if(count<k)
          
           return 0;
          
           else{
          
           printf("%d",q->data);
          
           return 1;
          
           }
        
}
            
               1
            
             typedef 
            
              int
            
            
               ElemType;
            
            
               2
            
                          typedef 
            
              struct
            
            
               LNode{
            
            
               3
            
            
                                 ElemType data;
            
            
               4
            
            
              struct
            
             LNode *
            
              next;
            
            
               5
            
                 }LNode, *
            
              LinkList;
            
            
               6
            
            
               7
            
            
              int
            
             Search(LinkList L, 
            
              int
            
            
               k){
            
            
               8
            
                        LNode *p=L->next, *q=L->
            
              next;
            
            
               9
            
            
              int
            
             count=
            
              0
            
            
              ;
            
            
              10
            
            
              while
            
            (p!=
            
              NULL){
            
            
              11
            
            
              if
            
            (count<k)count ++
            
              ;
            
            
              12
            
            
              else
            
             q=q->
            
              next;
            
            
              13
            
                              p=p->
            
              next;
            
            
              14
            
            
                  }
            
            
              15
            
            
              if
            
            (count<
            
              k)
            
            
              16
            
            
              return
            
            
              0
            
            
              ;
            
            
              17
            
            
              else
            
            
              {
            
            
              18
            
                     printf(
            
              "
            
            
              %d
            
            
              "
            
            ,q->
            
              data);
            
            
              19
            
            
              return
            
            
              1
            
            
              ;
            
            
              20
            
            
                  }
            
            
              21
            
            
              22
            
             }
          
          
        15.设头指针为L的带有表头结点的非循环双向链表,其每个结点除了有pred(前驱指针),data和next域外,还有一个访问频度域freq。在链表被启用前,其值均初始化为零。每当在链表中进行一次Locate(L ,x )运算时,令元素值为x的结点中freq域的值增1,并使此链表中结点保持按访问频度递减的序列排列,同时最近访问的结点排在频度相同的结点的前面,以便使频繁访问的结点总是靠近表头。使编写符合上述要求的Locate(L ,x )运算的算法,该运算为函数过程,返回找到结点的地址,类型为指针型。
设计思想: 首先找到链表中数据值为x的结点,查到后,将结点从链表上摘下,然后顺着结点的前驱查到该结点的插入位置。频度递减,且排在同频度的第一个。
 
        
          DLinkList Locate(DLinkList &L, ElemType 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->freq<p->freq&&q!=L)
          
           q=q->pred;
          
           p->next=q->next;
          
           q->next->pred=p;
          
           q->next=p;
          
           p->pred=q;
          
           }
          
           return p; //返回值为x的结点的指针
          
          }
        
            
               1
            
             DLinkList Locate(DLinkList &
            
              L, ElemType x){
            
            
               2
            
                       DNode *p=L->next, *
            
              q;
            
            
               3
            
            
              while
            
            (p&&p->data!=
            
              x)           
            
            
               4
            
                              p=p->
            
              next;
            
            
               5
            
            
              if
            
            (!
            
              p){
            
            
               6
            
                           printf(
            
              "
            
            
              不存在值为x的结点\n
            
            
              "
            
            
              );
            
            
               7
            
                           exit(
            
              0
            
            
              )
            
            
               8
            
            
                  }
            
            
               9
            
            
              else
            
            
              {
            
            
              10
            
                           p->freq++
            
              ;
            
            
              11
            
                           p->next->pred=p->
            
              pred;
            
            
              12
            
                           p->pred->next=p->
            
              next;
            
            
              13
            
                           q=p->
            
              pred;
            
            
              14
            
            
              while
            
            (q->freq<p->freq&&q!=
            
              L)
            
            
              15
            
                                    q=q->
            
              pred;
            
            
              16
            
                           p->next=q->
            
              next;
            
            
              17
            
                           q->next->pred=
            
              p;
            
            
              18
            
                           q->next=
            
              p;
            
            
              19
            
                           p->pred=
            
              q;
            
            
              20
            
            
                  }
            
            
              21
            
            
              return
            
             p;          
            
              //
            
            
              返回值为x的结点的指针
            
            
              22
            
             }
          
          
        欢迎查看关于顺序表的学习,见上篇 http://www.cnblogs.com/tracylining/p/3394038.html


 
               
					 
					