您的位置:首页 > 其它

模拟指针(simulated pointer)

2014-04-15 11:18 330 查看
模拟指针,也就是清华严老师《数据结构-C语言描述》中的静态链表,静态链表的引用是使用一段连续的存储区还模拟指针的功能,可以有效的利用一段连续内存进行一定范围内可变的子链表的空间分配,此数据结构原理比较简单,但是实现起来(至少我个人感觉)有一些绕,原因在于结点的指针域和所申请的整个空间数组的下标都是用整型来表示,极易出错,由于使用连续存储区,稍有不甚将指针地址错写成数组下标则很容易出错并且很难被发现。
  以下为本次实现的模拟指针代码,由三个文件构成:

  1、 simulatedPointer.h 定义了模拟指针的一些基本结构和方法

  2、excp.h       和前面一样,包含定制的异常类。

  3、simulatedPointer.cp 测试用的主函数

//simulatedPointer.h
#ifndef __SIMULATEDPOINTER__
#define __SIMULATEDPOINTER__
#include <iostream>
#include "excp.h"
using namespace std;

template<class T>
class SimPointerList;

template<class T>
class Node {
public:
friend class SimPointerList<T>;
private:
T data;
int next;
};

template<class T>
class SimPointerList {
public:
SimPointerList(int maxaSize = 10);
~SimPointerList(){delete [] list;}
int getFreeNode();
void recycleFreeNode(int i);
bool isEmpty() const;
int getLength() const;
SimPointerList<T>& deleteElement(int k, T& x);
SimPointerList<T>& insertElement(int k, const T& x);
void findElement(int k, T& x) const;
int searchElement(const T& x) const;
void output(ostream& out) const;
int getFreeCapacity() const;
private:
int freeHeader;//point to the head of the free-list
int usedHeader;
int maxSize;
Node<T> *list;
};

template<class T>
SimPointerList<T>::SimPointerList(int maxaSize)
{
maxSize = maxaSize;
freeHeader = 0;
usedHeader = -1;
list = new Node<T>[maxSize];
for (int i=0; i<maxSize-1;i++)
list[i].next = i+1;
list[maxSize-1].next = -1;
}

template<class T>
int SimPointerList<T>::getFreeNode()
{
if (freeHeader == -1)
throw FullMemory();
int i = freeHeader;
freeHeader = list[i].next;
list[i].next=-1;
return i;
}

template<class T>
void SimPointerList<T>::recycleFreeNode(int i)
{
if (i<0 || i>=maxSize)
throw OutOfBounds();
list[i].next = freeHeader;
freeHeader = i;
}

template<class T>
bool SimPointerList<T>::isEmpty() const
{
return usedHeader == -1;
}

template<class T>
int SimPointerList<T>::getLength() const
{
int len = 0;
if (usedHeader != -1)
for (int begin=usedHeader; begin!=-1; begin=list[begin].next)
len++;
return len;
}

template<class T>
SimPointerList<T>& SimPointerList<T>::deleteElement(int k, T& x)
{
if (k<=0 || k>getLength())
throw OutOfBounds();
int index = 0;
if (k == 1)
{
index = usedHeader;
usedHeader = list[usedHeader].next;
}
else if (getLength()==2 && k == 2)
{
index = list[usedHeader].next;
list[usedHeader].next = -1;
}
else
{
int prior = usedHeader;
for (int i=1; i<k-1; i++)
prior = list[prior].next;
index = list[prior].next;
list[prior].next = list[list[prior].next].next;
}
x = list[index].data;
list[index].next = -1;
recycleFreeNode(index);
return *this;
}

template<class T>
SimPointerList<T>& SimPointerList<T>::insertElement(int k, const T& x)
{
int len = getLength();
if (k<1 || k>len+1)
throw OutOfBounds();
if (len == maxSize)
throw FullMemory();
int index = getFreeNode();//.next field has been setted by -1
list[index].data = x;
if (usedHeader == -1 || k == 1)
{
list[index].next = usedHeader;
usedHeader = index;
return *this;
}

int begin = usedHeader;
for (int i=1; i<k-1; i++)
begin = list[begin].next;
list[index].next = list[begin].next;
list[begin].next = index;
return *this;
}

template<class T>
int SimPointerList<T>::getFreeCapacity() const
{
return maxSize - getLength();
}

template<class T>
void SimPointerList<T>::findElement(int k, T& x) const
{
if (k<=0 || k>getLength())
throw OutOfBounds();
int index = usedHeader;
for (int i=1; i<k; i++)
index = list[index].next;
x = list[index].data;
}

template<class T>
int SimPointerList<T>::searchElement(const T& x) const
{
int index = usedHeader;
int len = 0;
while (index != -1)
{
if (list[index].data == x)
break;
index = list[index].next;
len++;
}
return len;
}

template<class T>
void SimPointerList<T>::output(ostream& out) const
{
int len = usedHeader;
while (len != -1)
{
out<<list[len].data<<" ";
len = list[len].next;
}
}

template<class T>
ostream& operator<<(ostream& out, const SimPointerList<T>& x)
{
x.output(out);
return out;
}
#endif


//excp.h
#ifndef _EXCP_
#define _EXCP_
#include <new>
using namespace std;

class OutOfBounds {
public:
OutOfBounds(){}
};

class FullMemory {
public:
FullMemory(){}
};

void my_new_handler()
{
throw FullMemory();
}

new_handler old_handler = set_new_handler(my_new_handler);
#endif


//simulatedPointer.cpp
#include <iostream>
#include "excp.h"
#include "simulatedPointer.h"
using namespace std;

int main()
{
try{
SimPointerList<int> L(10);
cout<<"length : "<<L.getLength()<<endl;
L.insertElement(1, 2).insertElement(2, 6).insertElement(2, 4).insertElement(1, 5);
cout<<"length : "<<L.getLength()<<endl;
int x;
cout<<L<<endl;
L.findElement(2, x);
cout<<"The second element is : "<<x<<endl;
L.deleteElement(2, x);
cout<<"delete : "<<x<<endl;
cout<<"After delete : "<<L<<endl;
cout<<"new length is : "<<L.getLength()<<endl;
L.insertElement(2, 3).insertElement(1, 10);
cout<<"Least : "<<L<<endl;
cout<<"Now the length is : "<<L.getLength()<<endl;
}
catch(OutOfBounds e)
{
cout<<"out of bounds error occured"<<endl;
}
catch(FullMemory e)
{
cout<<"full memory error occured"<<endl;
}
return 0;
}


总结:

  1、如果要以传统思维来规范数组位置(下标从1开始),那就时刻要注意,在代码中时时小心处理和机器表示的区别,或者浪费一个存储空间list[0]以保持一致,

  2、要区分开模拟的链表下标和数组下标(因为这个,找了近两个小时的BUG,整个人都快疯掉了)。

  3、代码注意规范,变量、方法名尽量表达内丰含意。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: