/*
问题描述:双向链表L(结点中含有fre频度),每次访问元素后,元素按访问频度递减次序排列
说明: 这个问题题非常向操作系统中应用的一些算法了,比如说涉及到内存、磁盘中数据的访问,换出等。这个链表中保存的是按照最近最常使用的顺序排列的。
*/
#include <iostream>
using namespace std;
typedef struct DNode
{
int data; //数据
DNode *pre,*next; //前一个,后一个指针
int fre; //访问频度,初始化为0
}DNode,*DLinklist;
void CreateDList(DLinklist &Dl)
{
DNode * head = new DNode,*temp;
head->fre = -1;
head->data = -1;
head->next = NULL;
head->pre = NULL;
int val;
cin>>val;
while(val != 9999)
{
temp = new DNode;
temp->fre = 0;
temp->data = val;
if(head->next != NULL)
head->next->pre = temp;
temp->next = head->next;
head->next = temp;
temp->pre = head;
// temp->next = NULL;
cin>>val;
}
Dl = head;
}
//按访问频繁度排序元素
void Locate_x(DLinklist &DL,int x)
{
DNode * p = DL->next,*temp_pre = NULL,*temp_swa = NULL;
DNode *swa_bef = NULL,*swa_aft = NULL,*p_bef = NULL,*p_aft = NULL;
// cout<<"test"<<endl;
while(p != NULL)
{
if(x == p->data)
{
++p->fre;
temp_pre = p->pre;
while(temp_pre -> fre != -1 && temp_pre->fre <= p->fre )
{
temp_pre = temp_pre->pre;
}
temp_swa = temp_pre->next; //p的元素将放在temp_swa的元素前面
//如果前移的元素不等于本身
if(temp_swa != p)
{
//p元素前移
swa_bef = temp_swa->pre; //temp_swa的前一个元素
swa_aft = temp_swa->next; //temp_swa的后一个元素
p_bef = p->pre; //p的前一个元素
p_aft = p->next; //p的后一个元素
p_bef->next = p_aft;
if(p_aft != NULL)
p_aft->pre = p_bef;
p->next = temp_swa;
p->pre = swa_bef;
swa_bef->next = p;
swa_bef->next = p;
temp_swa->pre = p;
}
break;
}
else
p = p->next;
}
}
//顺序输出单链表中的元素
void PrintDList(DLinklist L)
{
DNode *p;
p = L->next;
while(p!=NULL)
{
if(p == L->next)
cout<<p->data;
else
cout<<" "<<p->data;
p = p->next;
}
cout<<endl;
}
总结:对于链表的插入、删除有一点麻烦的就是会涉及到改变指针指向的问题。一不小心就会出现断链等错误。在这里采取了最直接的方法,就是把涉及到的结点都表示出来,这样虽然浪费了一点空间,但是,改变指针就方便多了。
其实在实际应用中还可以考虑一些简便的方法来处理注入交换结点、删除等问题。
比如说对于交换结点,我们可以直接交换其中的值,这样就不用改变指针了。对于删除可以采用一种叫做“懒惰删除”的方法,就是不删除,而是增加一个特殊标志,代表其删除了。这样也能达到简化的效果。