雙向連結串列L每次訪問元素後,元素按訪問頻度遞減次序排列
阿新 • • 發佈:2019-01-28
/*
問題描述:雙向連結串列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;
}
總結:對於連結串列的插入、刪除有一點麻煩的就是會涉及到改變指標指向的問題。一不小心就會出現斷鏈等錯誤。在這裡採取了最直接的方法,就是把涉及到的結點都表示出來,這樣雖然浪費了一點空間,但是,改變指標就方便多了。
其實在實際應用中還可以考慮一些簡便的方法來處理注入交換結點、刪除等問題。
比如說對於交換結點,我們可以直接交換其中的值,這樣就不用改變指標了。對於刪除可以採用一種叫做“懶惰刪除”的方法,就是不刪除,而是增加一個特殊標誌,代表其刪除了。這樣也能達到簡化的效果。