引入跳躍鏈表的目的是爲了加速查找過程。而加速策略其中一個非常重要的觀點就是並非所有的元素使用的頻率都相同。我們自然希望高頻使用的元素在鏈表的頭部,而低頻的在鏈表尾部。單向鏈表和雙向鏈表需要進行順序查找以定位某個元素,還可以用某種方法動態地組織鏈表,從而提高查找效率。有許多不同的方法可以組織鏈表,比較常見的有如下四種:
- 前移法:在找到需要的元素之後,把它放到鏈表的開頭。
- 換位法:在找到需要的元素之後,只要它不在鏈表的開頭就與其前驅節點交換位置。
- 計數法:根據元素被訪問的次數,對鏈表進行排序。
- 排序法:根據被考察信息自身的屬性,對鏈表進行排序。
前移法代碼實現如下:
// 自組織鏈表(前移法)實現
#include<iostream>
using namespace std;
// 節點類
template<class T>
class Node {
public:
Node() {
next = 0;
}
Node(T e, Node* p = 0) :data(e), next(p) {}
T data; //節點信息
Node<T>* next; //下一節點地址
};
// 單向鏈表類
template<class T>
class ZList {
public:
ZList();
virtual ~ZList();
bool isEmpty() { //是否爲空鏈表
return 0 == head;
}
void addToHead(T); //在頭結點添加新節點
void deleteNode(T); //刪除指定節點
void visit(T); //訪問指定節點
void print();
private:
Node<T>* head; //頭節點
};
template<class T>
ZList<T>::ZList() {
head = 0;
}
template<class T>
ZList<T>::~ZList(){
for (Node<T>* p = 0; !isEmpty();) {
p = head->next;
delete head;
head = p;
}
}
template<class T>
void ZList<T>::print() {
Node<T>* p = head;
while (p != NULL) {
cout << p->data << " ";
p = p->next;
}
cout << endl;
}
template<class T>
void ZList<T>::addToHead(T d) {
head = new Node<T>(d, head);
}
template<class T>
void ZList<T>::deleteNode(T d) {
if (head == 0) { // if non-empty list;
return;
} else if (head->data == d) {
Node<T>* tmp = head;
head = head->next;
delete tmp;
return;
}
Node<T>* p = head;
while (p->next != NULL && p->next->data != d) {
p = p->next;
}
if (p->next != NULL) {
Node<T>* tmp = p->next;
p->next = tmp->next;
delete tmp;
}
}
template<class T>
void ZList<T>::visit(T d) {
if (head == 0) { // if non-empty list;
return;
} else if (head->data == d) {
cout << "visit " << d << endl;
return;
}
Node<T>* p = head;
while (p->next != NULL && p->next->data != d) {
p = p->next;
}
if (p->next != NULL) {
Node<T>* tmp = p->next;
p->next = tmp->next;
Node<T>* tmp_head = head;
head = tmp;
head->next = tmp_head;
}
}
int main() {
ZList<int> list;
list.addToHead(10);
list.addToHead(20);
list.addToHead(30);
list.print();
list.visit(10);
list.print();
return 0;
}