1. 程式人生 > >雙向連結串列L每次訪問元素後,元素按訪問頻度遞減次序排列

雙向連結串列L每次訪問元素後,元素按訪問頻度遞減次序排列

/*
問題描述:雙向連結串列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; }

總結:對於連結串列的插入、刪除有一點麻煩的就是會涉及到改變指標指向的問題。一不小心就會出現斷鏈等錯誤。在這裡採取了最直接的方法,就是把涉及到的結點都表示出來,這樣雖然浪費了一點空間,但是,改變指標就方便多了。

其實在實際應用中還可以考慮一些簡便的方法來處理注入交換結點、刪除等問題。
比如說對於交換結點,我們可以直接交換其中的值,這樣就不用改變指標了。對於刪除可以採用一種叫做“懶惰刪除”的方法,就是不刪除,而是增加一個特殊標誌,代表其刪除了。這樣也能達到簡化的效果。