数据结构静态链表的一个实现。
思想是开一个静态数组,每个数组元素中有它的后继元素的位置序号。并且用备用链表的方式来对删除的元素留出的空间进行循环使用。
具体的讲解数据结构书上都有,这是在看一个小的题目时想到可以用静态链表来实现更加方便,并且时间复杂度低才使用的。具体题目如下:
1
.停车场管理
问题描述:
设停车场是一个可停放
n辆汽车的狭长通道,且只有一个大门可供汽车进出。汽车在停车场内按车辆到达时间的先后顺序,依次由北向南排列(大门在最南端,最先到达的第一辆车停放在停车场的最北端),若停车场内已停满n辆汽车,则后来的汽车只能在门外的便道上等候,一旦有车开走,则排在便道上的第一辆车即可开入;当停车场内某辆车要离开时,在它之后进入的车辆必须先退出车场为它让路,待该辆车开出大门外,其他车辆再按原次序进入车场,每辆停放在车场的车在它离开停车场时必须按它停留的时间长短交纳费用。试为停车场编制按上述要求进行管理的模拟程序。
基本要求
以栈模拟停车场,以队列模拟车场外的便道,按照从终端读入的输入数据序列进行模拟管理。每一组输入数据包括三个数据项:汽车“到达”或“离去”信息、汽车牌照号码以及到达或离去的时刻。对每一组输入数据进行操作后的输出信息为:若是车辆到达,则输出汽车在停车场内或便道上的停车位置;若是车辆离去,则输出汽车在停车场内停留的时间和应交纳的费用(在便道上停留的时间不收费)。栈以顺序结构实现,队列以链表结构实现。
测试数据
设
n=2,输入数据为:(‘A’,1,5),(‘A’,2,10),(‘D’,1,15),(‘A’,3,20),(‘A’,4,25),(‘A’5,30),(‘D’,2,35),(‘D’,4,40),(‘E’,0,0)。其中:‘A’表示到达(arrival);‘D’表示离去(departure);‘E’表示输出结束(end)。
遵照题上讲的用栈和队列来实现了,感觉不是很爽,你得用一个辅助栈来存放为让道而从停车场临时退出的汽车,并且还得压回原栈,时间复杂度较高。思考了下,发觉用静态链表可以实现,汽车进入停车场相当于加入链表尾部,汽车离开相当于在链表中删除一个元素,并且链表中元素个数有上限,适合采用静态链表。于是就实现了一个,程序只是简单测试,可能还存在一些问题,写在这仅供参考,以后需要用到静态链表可以直接拿过来改改。
静态链表的整个实现都在ParkingLane这个类中,包括在链表尾部插入一个元素以及删除链表中一个元素
#define MAXN 5
#include <iostream>
#include <deque>
using namespace std;
#if 0
//MyStack是自己实现的一个基于静态数组的栈
template
class MyStack
{
public:
MyStack()
{
top = -1;
capacity = 0;
}
void setCapacity(int cap)
{
capacity = cap;
}
void push(const T& elem)
{
if(top < capacity - 1)
{
stack[++top] = elem;
}
}
T pop()
{
T elem;
if(top > -1)
{
elem = stack[top--];
}
return elem;
}
T topElem()
{
T elem;
if(top != -1)
{
elem = stack[top];
}
return elem;
}
bool empty()
{
return top == -1;
}
bool full()
{
return top >= capacity - 1;
}
protected:
T stack[MAXN];
int top;
int capacity;
};
#endif
//静态链表实现
template
class ParkingLaneLot
{
public:
T parkingInfo;
int cur; //下一辆车的停靠位置
};
template
class ParkingLane
{
public:
ParkingLane()
{
ra = 0;
av = 1;
}
~ParkingLane()
{}
void init(int cap)
{
capacity = cap;
for(int i = 1; i < capacity; i++)
{
stack[i].cur = i + 1;
}
stack[0].cur = -1;
stack[capacity].cur = -1;
}
int remove(const T& elem)
{
int removePos = 0;
bool found = false;
//查找等于elem的元素在stack中的前驱位置
while(stack[removePos].cur != -1 && !found)
{
found = (stack[stack[removePos].cur].parkingInfo == elem);
if(!found)
{
removePos = stack[removePos].cur;
}
}
if(found)
{
//找到等于elem的元素,removePos指向elem元素的前驱
int loc = stack[removePos].cur;
if(loc == ra)
{
//调整尾节点位置
ra = removePos;
}
stack[removePos].cur = stack[loc].cur;
//加入备用链表
stack[loc].cur = av;
av = loc;
return loc;
}
return -1;
}
bool push(const T& elem)
{
if(av != -1)
{
//从备用链表上获取备用节点
int pos = av;
av = stack[av].cur;
//加入链表的尾部
stack[pos].parkingInfo = elem;
stack[pos].cur = stack[ra].cur;
stack[ra].cur = pos;
ra = pos;
return true;
}
else
{
//链表已满
return false;
}
}
bool empty()
{
return stack[0].cur == -1;
}
bool full()
{
return av == -1;
}
T* get(int pos)
{
if(pos >0 && pos <= capacity)
{
return &stack[pos].parkingInfo;
}
return NULL;
}
protected:
ParkingLaneLot
stack[MAXN+1];
int ra; // 尾节点位置
int av; //备用链表头结点位置
int capacity;
};
#define ARRIVE 'A'
#define LEAVE 'D'
class ParkingInfoObj
{
public:
bool operator ==(const ParkingInfoObj &obj)
{
return obj.id == id;
}
int id;
int in_time;
};
class ParkingSpace
{
public:
ParkingSpace(int n,int parkingPrice)
{
lane.init(n);
price = parkingPrice;
}
//车辆到达
void processCarArrival(int id,int time)
{
if(lane.full())
{
waitingQ.push_back(id);
}
else
{
ParkingInfoObj parkObj;
parkObj.id = id;
parkObj.in_time = time;
lane.push(parkObj);
}
}
//车辆离开
void processCarLeave(int id,int time)
{
bool found = false;
ParkingInfoObj parkObj;
parkObj.id = id;
int pos = lane.remove(parkObj);
if(pos != -1)
{
//计算费用
ParkingInfoObj* parkObjRef = lane.get(pos);
if(parkObjRef != NULL)
{
int elapse = time - parkObjRef->in_time;
printf("Car[%d]: %d/n",parkObj.id,elapse * price);
}
}
if(!lane.full() && waitingQ.size() > 0)
{
ParkingInfoObj obj;
obj.id = waitingQ.front();
obj.in_time = time;
lane.push(obj);
waitingQ.pop_front();
}
}
protected:
//MyStack
lane;
//MyStack
helpLane;
ParkingLane
lane;
deque
waitingQ;
int price;
};
int main(int argc,char **argv)
{
char buf[MAXLINE];
int n,parkingPrice;
cin>>n>>parkingPrice;
ParkingSpace parkingSpace(n,parkingPrice);
do
{
char op;
int id,time;
cin>>op>>id>>time;
if(op == ARRIVE)
{
//new car arrives
parkingSpace.processCarArrival(id,time);
}else if(op == LEAVE)
{
//car in lane leaves
parkingSpace.processCarLeave(id,time);
}
else
{
break;
}
}while(true);
return 0;
}
进一步思考,利用两个独立的栈存在的问题包括需要两倍于最大停车数目的辅助栈(空间复杂度),并且要把元素在栈与辅助栈之间来回移动(时间复杂度)。关于降低空间消耗,书上给出了共享栈的想法。两个栈共享一块存储空间,大小为最大停车数目。两个栈的栈底分别在存储空间的两端,栈顶向中间生长,直到两个栈顶碰头。主栈中需要移动元素时,先弹出元素,栈顶向栈底移动,这样另外一个辅助栈就可以利用主栈中原来的存储空间来存放从主栈中弹出的元素。通过空间的重复使用来降低空间开销。
实现略