一、題目
說明如何對每個元素僅用一個指標np[x](而不是兩個指標next和prev)來實現雙鏈表。假設所有指標值都是k位的整型數,且定義np[x] = next[x] XOR prev[x],即next[x]和prev[x]的k位異或(NIL用0表示)。注意要說明訪問表頭所需的資訊,以及如何?在該表上的SEARCH、INSERT和DELETE操作。如何在O(1)時間內實現這樣的表。
二、思路
np[x] = next[x] XOR prev[x],根據異或的性質,next[x] = np[x] XOR prev[x],prev[x] = next[x] XOR np[x],只要知道這個結點的下一個結點的地址,就能求出它上一個結點的地址,或者,只要知道這個結點上一個結點的位置,就知道求出它的下一個結點的位置
在鏈表中定義一個頭結點,這個結點的位置是已知的,根據上文的結論,就可以依次遍曆鏈表中的每個結點,進行於SEARCH、INSERT和DELETE操作了
三、代碼
#include <iostream>#include <string>using namespace std;//結點struct node{int key;//值unsigned int np;//指標,地址是32位的,所以要用不帶正負號的整數表示node(int k):key(k),np(0){}};//鏈表struct list{node head;//頭結點,作為哨兵,用於尋找第一個結點list():head(0){}};//插入操作void Insert(list *l, int k){//產生一個新的結點node *A = new node(k);//要插入到鏈表的第一個位置,即head->next處//A->next是head->next,其地址為l->head.np,A->prev是head,其地址為(unsigned int)(&(l->head))//A->np是A->next ^ A->prevA->np = l->head.np ^ (unsigned int)(&(l->head));//若原鏈表不為空白,則要修改原head->next結果的指標,因為它的prev發生了改變node *p = (node*)l->head.np;if(p){//NewNp = OldNp ^ OldNext ^ OldPrev ^ NewNext ^ NewPrev;//在這裡,只是p->prev有改動,p->next不變,因此簡化為NewNp = OldNp ^ OldPrev ^ NewPrev;//OldPrev是Head,其地址為(unsigned int)(&(l->head)),NewPrev是新結點A,其地址為(unsigned int)Aunsigned int temp = p->np;temp = temp ^ (unsigned int)A ^ (unsigned int)(&(l->head));p->np = temp;}l->head.np = (unsigned int)A;}//輸出鏈表void Print(list *l){//找到第一個結點的位置,因為Head->prev=0,Head->next=Head->np,直接可以得到第一個結點的位置unsigned int p = l->head.np, q;//q表示為p->prev結點的位置q = (unsigned int)(&(l->head));//把p轉換為指標while((node*)p){//輸出cout<<((node*)p)->key<<' ';//p指向下一個元素unsigned int t = p;p = ((node*)p)->np ^ q;q = t;}cout<<endl;}//刪除void Delete(list *l, int k){//依次遍曆每個元素,遍曆方法同Search unsigned int p = l->head.np, q;q = (unsigned int)(&(l->head));while((node*)p){if(((node*)p)->key == k)break;unsigned int t = p;p = ((node*)p)->np ^ q;q = t;}//p是待刪除元素的地址,q是待刪除元素的上一個元素的地址,r是待刪除元素的下一個元素的地址if((node*)p == NULL)return;int r = ((node*)p)->np ^ q;//修改q->next和修改r->prev,修改方法與INSERT中的修改方法相似((node*)q)->np = ((node*)q)->np ^ p ^ r;if((node*)r != NULL)((node*)r)->np = ((node*)r)->np ^ p ^ q;//刪除p指向的結點delete (node*)p;}int main(){string str;list *L = new list;int x;while(1){cin>>str;if(str == "P"){Print(L);}else if(str == "I"){x = rand() % 100;cout<<x<<endl;Insert(L, x);}else if(str == "D"){cin>>x;Delete(L, x);}}return 0;}