链表的数组实现中,令链表和自由表变得紧凑《算法导论》10.3-5
Posted meixiaogua
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了链表的数组实现中,令链表和自由表变得紧凑《算法导论》10.3-5相关的知识,希望对你有一定的参考价值。
- 有一个双向链表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" << " " << "key" << endl;
int curPos = listHead;
while(curPos != -1)
{
cout << curPos << " " << 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的主要内容,如果未能解决你的问题,请参考以下文章