设有一个双向循环链表,每个结点中除有pre,data和next三个域外,还增设了一个访问频度域freq。在链表被起用之前,频度域freq的值均初始化为零,而每当对链表进行一次Locate(x)的操作后,被访问的结点(即元素值等于x的结点)中的频度域freq的值便增1,同时调整链表中结点之间的次序,使其按访问频度非递增的次序顺序排列,以便始终保持被频繁访问的结点总是靠近表头结点。试编写符合上述要求的Locate操作的算法。
#include <stdio.h>
#include <stdlib.h>
#define OK 1
#define ERROR 0
typedef int Status;
typedef int ElemType;
typedef struct DuLNode
{
int freq;
ElemType data;
struct DuLNode *pre;
struct DuLNode *next;
} DuLNode,*DulLinkList;
Status Locate(DulLinkList &L,ElemType e);
Status CreateList(DulLinkList &L,int n,ElemType Data[]);
Status OutputDul(DulLinkList &L);
int main()
{
DulLinkList L;
ElemType data[10] = {1,2,3,4,5,6,7,8,9,10};
ElemType temp[10] = {1,8,6,2,3,4,8,5,8,9};
CreateList(L,10,data);
printf("原表:\n");
OutputDul(L);
for(int i = 1; i <= 10; i++)
Locate(L,temp[i - 1]);
printf("\n操作后:\n");
OutputDul(L);
printf("\n访问次数:\n");
for(DulLinkList p = L->next; p != L; p = p->next)
printf("%2d ",p->freq);
return 0;
}
Status Locate(DulLinkList &L, ElemType x)
{
DulLinkList p,pre;
int i = 1;
if(!L || L->next == L)
return 0;
pre = L;
p = L->next;
while(p != L && p->data != x)
{
i++;
pre = p;
p = p->next;
}
if(p != L)
{
p->freq++;
while(pre != L && pre->freq < p->freq)
{
i--;
pre = pre->pre;
}
if(pre->next != p)
{
p->next->pre = p->pre;
p->pre->next = p->next;
p->next = pre->next;
p->pre = pre;
pre->next->pre = p;
pre->next = p;
}
return i;
}
return 0;
}
Status CreateList(DulLinkList &L, int n, ElemType Data[])
{
DulLinkList s,p;
int i;
L = (DulLinkList)malloc(sizeof(DuLNode));
if(!L)
return ERROR;
L->next = L->pre = L;
for(i = 1,p = L; i <= n; i++,p = p->next)
{
s = (DulLinkList)malloc(sizeof(DuLNode));
if(!s)
return ERROR;
s->data = Data[i-1];
s->freq = 0;
s->next = L;
s->pre = p;
p->next = s;
if(p == L)
p->pre = s;
}
return OK;
}
Status OutputDul(DulLinkList &L)
{
DulLinkList p;
if(!L)
return ERROR;
else
{
p = L->next;
while(p != L)
{
printf("%2d ",p->data);
p = p->next;
}
}
return OK;
}