题目:
有一个双链表L,每一个节点中除有prior、data和next三个域外,还有一个访问频度域freq,在链表被起用之前,其值均初始化为零。每当进行LocateNode(L,x)运算时,令元素值为x的节点中freq域的值加1,并调整表中节点的次序,使其按访问频度的递减序列排序,以便使频繁访问的节点总是靠近表头。试写一符合上述要求的LocateNode运算的算法
分析:
当x找到当前的节点的时候,节点的freq自增1,然后和前面的pre节点的freq相比较,若当前节点的freq是大于pre的,则将两节点的数据进行交换
LocateNode函数为
bool LocateNode(Node *L,int x) { Node *p=L->next; while(p!=NULL&&p->data!=x)//开始查找等于x的元素 p=p->next; //当查到存在等于p的节点的时候 if(p!=NULL)//p不等于空,说明找打了需要的数字 { ++p->fre;//数字对应的频率自增 Node *pre=p->prior; if(pre->data!=1000)//开始交换 { while(pre->data!=1000&&pre->fre<p->fre) { pre->data=pre->data+p->data-(p->data=pre->data);//换数据 pre->fre=pre->fre+p->fre-(p->fre=pre->fre); p=pre;//换节点 pre=pre->prior; } return true;//更换成功 } else return true;//默认就是第一个节点,就不需要往前移动了 } else return false;//没查到,p为空 }
总体测试代码:
#include<stdio.h> #include<stdlib.h> #include<stdbool.h> typedef struct node{ int data; int fre; struct node *prior; struct node *next; }Node; void creat_LinkList(Node *L,int a[],int n) { Node *p=L; for(int i=0;i<n;i++) { Node *s=(Node *)malloc(sizeof(Node)); s->data=a[i]; s->fre=0; s->next=NULL; s->prior=p; p->next=s; p=s; } } bool LocateNode(Node *L,int x) { Node *p=L->next; while(p!=NULL&&p->data!=x)//开始查找等于x的元素 p=p->next; //当查到存在等于p的节点的时候 if(p!=NULL)//p不等于空,说明找打了需要的数字 { ++p->fre;//数字对应的频率自增 Node *pre=p->prior; if(pre->data!=1000)//开始交换 { while(pre->data!=1000&&pre->fre<p->fre) { pre->data=pre->data+p->data-(p->data=pre->data);//换数据 pre->fre=pre->fre+p->fre-(p->fre=pre->fre); p=pre;//换节点 pre=pre->prior; } return true;//更换成功 } else return true;//默认就是第一个节点,就不需要往前移动了 } else return false;//没查到,p为空 } void print(Node *L) { Node *p=L->next; int i=0; while(p!=NULL) { ++i; printf("%d(%d) ",p->data,p->fre); if(i%3==0) printf(" "); p=p->next; } } int main(){ int a[]={1,8,7,3,4,6,5,2}; int n=8; Node L={1000,0,NULL,NULL}; creat_LinkList(&L, a, n); int b[]={1,8,8,8,8,4,5,2,1}; for(int i=0;i<9;i++) LocateNode(&L, b[i]); printf("查找频率从大到小排序可的 "); print(&L); }