鏈表的數組實現中,令鏈表和自由表變得緊湊《算法導論》10.3-5
阿新 • • 發佈:2018-10-17
bject and elements 多少 lse tex com spa 使用
- 有一個雙向鏈表L,存儲於長度為m的數組。假設m個元素中有n個元素在鏈表L中,m-n個元素由自由表F管理。現在實現方法CompacifyList,它的功能是讓鏈表L中元素緊湊地占據數組的前n個元素,自由表F占據數組的後m-n個元素。運行時間O(n),只使用固定的額外存儲空間。
- 這道題可以這樣來思考,數組[0,n)區間是L的地盤,數組[n,m)區間是F的地盤,我們想要的結果是L和F雙方的元素都乖乖地待在自己家的地盤上。可是現在偏偏有一些淘氣的元素跑到了別人家的地界上,且有多少個L元素跑去了F家裏,相應地,就有多少F元素跑到了L家裏。我們要做的是同時從L和F鏈表頭開始查找,每當找出一個待在F家的L元素和一個待在L家的F元素,就對換他們兩個的位置,這樣他倆就都回到了自己家中。
#include <cassert> #include <iostream> using namespace std; struct Object { int prev; int key; int next; }; constexpr int SIZE = 10; Object array[SIZE]; int listHead; int freeHead; int listSize; void CompacifyList() { assert(listSize > 0); int freePrev = -1; int freeCur = freeHead; int freeNext = array[freeCur].next; int listPrev = array[listHead].prev; int listCur = listHead; int listNext = array[listHead].next; bool bNeedSwap = false; while(true) { //find next element of list to swap bNeedSwap = false; while(!bNeedSwap) { if(listCur < listSize) { listPrev = listCur; listCur = listNext; if(listCur == -1) break; else listNext = array[listCur].next; } else { bNeedSwap = true; } } if(listCur == -1) break; //find next element of freelist to swap bNeedSwap = false; while(!bNeedSwap) { if(freeCur >= listSize) { freePrev = freeCur; freeCur = freeNext; if(freeCur == -1) break; else freeNext = array[freeCur].next; } else { bNeedSwap = true; } } //swap int tmp = freeCur; freeCur = listCur; listCur = tmp; array[listCur].key = array[freeCur].key; //insert new listCur between listPrev and listNext array[listCur].prev = listPrev; array[listCur].next = listNext; if(listPrev != -1) array[listPrev].next = listCur; else listHead = listCur; //處理被交換元素是鏈表頭的邊界情況 if(listNext != -1) array[listNext].prev = listCur; //insert new freeCur between freePrev and freeNext if(freePrev != -1) array[freePrev].next = freeCur; else freeHead = freeCur; array[freeCur].next = freeNext; } } void Test() { //there are 5 objects in list, index = 2 8 6 3 9, key = 1 2 3 4 5 listHead = 2; array[2] = {-1, 1, 8}; array[8] = {2, 2, 6}; array[6] = {8, 3, 3}; array[3] = {6, 4, 9}; array[9] = {3, 5, -1}; listSize = 5; //there are 5 object in freelist, index = 1 4 5 0 7 freeHead = 1; array[1].next = 4; array[4].next = 5; array[5].next = 0; array[0].next = 7; array[7].next = -1; CompacifyList(); //L元素都排在數組下標0~4位置上 cout << "list elements:" << endl; cout << "pos" << "\t" << "key" << endl; int curPos = listHead; while(curPos != -1) { cout << curPos << "\t" << array[curPos].key << endl; curPos = array[curPos].next; } //F元素都排在數組下標5~9位置上 cout << "freeList elements:" << endl; curPos = freeHead; while(curPos != -1) { cout << curPos << endl; curPos = array[curPos].next; } } //運行結果是 list elements: pos key 2 1 1 2 4 3 3 4 0 5 freeList elements: 8 6 5 9 7 //寫給自己,我第一次寫這段代碼時出現的錯誤: 1. 忘記交換freeCur和listCur的值 2.忘記處理邊界情況freeHead和listHead
鏈表的數組實現中,令鏈表和自由表變得緊湊《算法導論》10.3-5