单链表第二十题(按频度排序)

文章描述了一个带有访问频度域的双向链表数据结构,每次Locate运算时会增加目标节点的访问频度并重新按频度排序,保持最近访问的节点在链表前端。提供的C代码实现了Locate函数,首先查找节点并更新其频度,然后在链表中找到合适位置进行插入,以保持链表的排序规则。
摘要由CSDN通过智能技术生成

 20.设头指针为L的带有表头节点的非循环双向链表,

      其每个节点中除有pred(前缀指针),data(数据)和next(后继指针)域外,

      还有一个访问频度域freq。在链表被启用前,其均值初始化为零。

      每当在链表中进行一次Locate(L,x)运算时,令元素值为X的节点中freq域的值增1,

       并使此链表中节点保持按访问频度非增(递减)的顺序排列,

       同时最近访问的节点排在频度相同的节点前面,以便使频繁访问的节点总是靠近表头。

      试编写符合要求的Locate(L,x)运算的算法,

       该运算为函数过程,返回找到节点的地址,类型为指针型。

/*

   给一个非循环双向链表增加一个free值,用以表示它的访问频率,每访问一次freq就+1,

   然后需要将该链表按照非增的顺序排列,同时最近访问的节点排在相同频度的节点的前面,

   以便使频繁访问的节点总是靠近表头。

   试编写符合上述要求的Locate(L,x)函数,该运算为函数过程,返回找到节点的地址,

    类型为指针型。

    分析:

           这道题咋一看很唬人,还引入了一个新概念,其实并不难,

            拆分开来其实就是:查找+排;

           我们需要先找到我们要访问的节点,更改它的ferq值,

           然后按照freq值的大小从表头寻找插入位置,这样便完成了一次locate操作。

*/
struct  Link{

      int  data;

      Link   *pre;

      Link  freq;

     int   freq;

};

#define_CRT_SECURE_NO_WARNINGS

#include<stdio.h>

#include<stdlib.h>

void  locate(Link  *h,int  num){

         int  flag=0;//找到标志

          Link  *pre=h,*p=h->next,*t,*preQ=h,*q;

          while(p){

                    if(p->data==num){//如果找到

                              flag=1//表示找到

                              p->freq++;//freq+

                               t=p;//将该节点保存起来

                               if(p->next){

                                    pre->next=p->next;//将该节点抠出来

                                      p->next->pre=pre;

                                    }

                                  else{

                                          pre->next=NULL;

                                           //这里也要注意,如果我们查找的节点是最后一个节点,

                                           //我们要将next指向NULL,不然之后遍历时会出问题.

                                            }

                              q=h->next;//这里需要注意,q应该始终指向改变了的首节点

                                 while(q){//进行排序

                                             if(t->freq>=q->freq){

                                                     //当找到的节点freq大于等于当前遍历节点时,插入

                                                      t->next=q;

                                                      q->next=t;

                                                      preQ->next=t;

                                                      t->pre=preQ;

                                                       break;

                                                 }

                                                 pre=p;

                                                  p=p->next;

                                         }

                 if(!flag){

                       printf("未找到该元素,序列不做改变");

              }

}

int  main(){

              int   n,data,num;

              Link  *head=(Link*)malloc(sizeof(Link));

              head->next=NULL;

               head->pre=NULL;

              Link  *p=head;

               printf("请输入节点个数",n=);

               scanf("%d",&n);

               for(int  i=0;i<n;i++){

                           printf("请输入第%d个节点值:",i+1);

                           scanf("%d",&data);

                            Link  *newP=(Link*)malloc(sizeof(Link));

                            newP->data=data;

                             newP->pre=p;

                              newP->freq=0;

                              p->next=newP;

                               p=newP;

                 }  

                    p->next=NULL;

                     do{

                           printf("请输入要查找的值,输入9999代表结束:num=");

                           scanf("%d",&num);

                           if(num==9999)   countine;//如果num=9999,跳入下一次循环

                            locate(head,num);

                            //p=head->next;

                              printf("调整后链表为:\n");

                                while(p){

                                          printf("%d",p->data);

                                           p=p->next;

                                    }                       

                            }while(num!=9999);

                         return  0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值