模拟指针(simulated pointer)
2014-04-15 11:18
330 查看
模拟指针,也就是清华严老师《数据结构-C语言描述》中的静态链表,静态链表的引用是使用一段连续的存储区还模拟指针的功能,可以有效的利用一段连续内存进行一定范围内可变的子链表的空间分配,此数据结构原理比较简单,但是实现起来(至少我个人感觉)有一些绕,原因在于结点的指针域和所申请的整个空间数组的下标都是用整型来表示,极易出错,由于使用连续存储区,稍有不甚将指针地址错写成数组下标则很容易出错并且很难被发现。
以下为本次实现的模拟指针代码,由三个文件构成:
1、 simulatedPointer.h 定义了模拟指针的一些基本结构和方法
2、excp.h 和前面一样,包含定制的异常类。
3、simulatedPointer.cp 测试用的主函数
总结:
1、如果要以传统思维来规范数组位置(下标从1开始),那就时刻要注意,在代码中时时小心处理和机器表示的区别,或者浪费一个存储空间list[0]以保持一致,
2、要区分开模拟的链表下标和数组下标(因为这个,找了近两个小时的BUG,整个人都快疯掉了)。
3、代码注意规范,变量、方法名尽量表达内丰含意。
以下为本次实现的模拟指针代码,由三个文件构成:
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、代码注意规范,变量、方法名尽量表达内丰含意。
相关文章推荐
- 字符设备 register_chrdev_region()、alloc_chrdev_region() 和 register_chrdev()。
- jsDevToo--js开发调试工具库
- Exchange Server 2013 高可用部署系列(五)外网访问和证书配置
- STM8/STM32 SPI模式的MAX7456代码
- SVN常用命令说明
- dhtmlXGrid 同一个列表区,不同列显示
- css小记
- php启用zlib压缩文件的配置方法
- 点击LinearLayout使用selector改变TextView字体颜色
- jsDevToo--js开发调试工具库
- 学习笔记2014/4/15
- 转:V$SQL,V$SQLAREA,V$SQLTEXT
- Eclipse超级完美汉化教程
- 获取页面中更新删除传过来的id
- hdu_1008 Elevator
- 自定义异常---RuntimeException
- Cracking the coding interview--Q19.5
- (1)html简介与基本文本格式化显示
- linux下卸载安装jdk
- 千帆过尽,只想循着一颗心