设有一头指针为L的带有表头结点的非循环双向链表,其每个结点中除有prior(前驱指针),data(数据)和next(后继指针)域外,还有一个访问频度域freq。在链表被起用前,其值均初始化为零。每当在链表中进行一次Locate(L,x)运算时,令元素值为x的结点中freq域的值增1,并使此链表中结点保持按访问频度非增(递减)的顺序排列,同时最近访问的结点排在频度相同的结点的最后,以便使频繁访问的结点总是靠近表头。试编写符合上述要求的Locate(L,x)运算的算法,该运算为函数过程,返回找到结点的地址,类型为指针型。
#include <iostream>
#include <time.h>
#include <stdlib.h>
typedef struct node{
int data;
node* next;
node* prev;
int freq;
}node,*list;
list Init()
{
list head=(list) malloc(sizeof (node));
head->next= nullptr;
head->data=-1;
head->freq=0;
head->prev= nullptr;
return head;
}
list Buynewnode(int x)
{
list tmp=new node;
tmp->next= nullptr;
tmp->data=x;
tmp->freq=0;
tmp->prev= nullptr;
return tmp;
}
list Locate(list head,int x)
{
list pointer=head;
while(pointer->next){
if(pointer->next->data==x) break;
else pointer=pointer->next;
}
if(pointer->next== nullptr) return nullptr;
pointer->next->freq++;
list tmp=pointer;
while(tmp!=head&&tmp->freq<=pointer->next->freq) tmp=tmp->prev;
if(tmp==pointer) return pointer->next;//如果已经是排好的就不要再交换了。
list t1=pointer->next->next,t2=pointer->next,t3=tmp->next;
pointer->next=t1;
if(t1) t1->prev=pointer;
tmp->next=t2;
t2->prev=tmp;
t2->next=t3,t3->prev=t2;
return t2;
}
int main() {
srand(time(nullptr));
list head=Init();
list pointer=head;
printf("Initian\n");
for(int i=0;i<10;i++)
{
pointer->next= Buynewnode(i+1);
pointer->next->prev=pointer;
pointer=pointer->next;
}
for(pointer=head->next;pointer!= nullptr;pointer=pointer->next) {
printf("%3d",pointer->data);
}
puts("");
printf("frequency\n");
for(pointer=head->next;pointer!= nullptr;pointer=pointer->next) {
printf("%3d",pointer->freq);
}
puts("");
printf("Input\n");
for(int i=0;i<100;i++)
{
int x=rand()%10+1;
printf("%3d",x);
Locate(head,x);
}
puts("");
printf("order\n");
for(pointer=head->next;pointer!= nullptr;pointer=pointer->next) {
printf("%3d",pointer->data);
}
puts("");
printf("frequency\n");
for(pointer=head->next;pointer!= nullptr;pointer=pointer->next) {
printf("%3d",pointer->freq);
}
puts("");
return 0;
}