数据结构与算法C++描述(5)---模拟指针及模拟链表
2017-10-12 22:39
891 查看
1、相关概念
1.1、模拟指针的定义
模拟指针可以理解为:在一个模拟空间中,存在一个指针数组,数组中的每个元素为指针类型,并且每个指针具有数据域和链接域(指向下一个数组中的指针)。1.2、模拟指针描述单链表、间接寻址描述单链表及普通单链表之间的区别:
普通单链表中,各个节点没有索引值;间接寻址描述单链表时,各个节点间的索引值满足一定的数学关系;
模拟指针描述单链表时,各个节点的索引值不用满足一定的数学关系,但每个节点的索引值唯一。
2、模拟指针的类定义及实现
利用C++语言,实现模拟指针的类定义,包括模拟空间类SimSpace和模拟节点类SimNode。初始时,模拟空间中存放了所有的节点(MaxSize个)。为了在模拟空间中实现模拟指针,那么,就必须在需要新节点的时候申请一个指向该节点的指针(从模拟空间中取出一个节点);同理,在不需要此节点的时候释放此节点的指针(向模拟空间中放入一个节点)。相当于C++函数new和delete。在程序中,利用Allocate()函数和Deallocate()函数实现。为了简单起便,上述操作在模拟空间的前部进行。2.1 模拟指针的类定义
template <class T> class SimSpace; template <class T> class SimChain; template <class T> class SimNode { friend SimSpace<T>; //友类模拟空间类 friend SimChain<T>; //友类模拟链表类 private: T data; //数据 int link; //指向下一个元素 }; template <class T> class SimChain; template <class T> class SimSpace { friend SimChain<T>; public: SimSpace(int MaxSize=100); ~SimSpace(); int Allocate(); //取出一个节点 void Deallocate(int &i); //放入第i个节点 private: int NumberOfNodes, frist; //NumberOfNodes为节点数目,frist为首节点索引值 SimNode<T> *node; //节点数组 };
2.2 成员函数实现
2.2.1 申请新的模拟空间
通过SimSpace类的构造函数实现。template <class T> SimSpace<T>::SimSpace(int MaxSize) { NumberOfNodes = MaxSize; //初始时,所有节点都是自由的 node = new SimNode<T>[NumberOfNodes]; //建立所有的节点,包括节点数据和指向下一节点的指针 for (int i = 0; i < NumberOfNodes - 1; i++) node[i].link = i + 1; //第一个节点 frist = 0; //最后一个节点 node[NumberOfNodes - 1].link = -1; } template <class T>
2.2.2 释放模拟空间
通过SimSpace类的析构函数实现。template <class T> SimSpace<T>::~SimSpace() { delete[] node; }
2.2.3 申请新的模拟指针
通过”int Allocate()”函数实现。函数返回申请后的节点索引值。//取出一个节点 template <class T> int SimSpace<T>::Allocate() { if (frist == -1) throw NoMerm(); int i = first; first=node[i].link; return i; }
2.2.4 释放节点i的模拟指针
通过”void Dellocate()”实现。//向模拟空间中放入第i个节点 template <class T> void SimSpace<T>::Deallocate(int &i) { if (i >= 0 && i <= NumberOfNodes) //合法输入 { frist = i; node[i].link = frist; i = -1; } else throw OutOfRange(); }
3、模拟链表
利用模拟指针操作单链表,包括以下操作:下面分别说明:
3.1 模拟链表类的定义
在类的定义中,关于模拟链表的创建和删除已经实现。//模拟链表类 template <class T> class SimChain { public: SimChain() { frist = -1; } //给定首节点索引值 ~SimChain() { Destroy(); } void Destroy(); //清空表 int Length() const; //返回链表长度 //寻找第k个位置的元素,若存在,则将值赋给x,并返回true;否则,返回false bool Find(int k, T &x) const; //寻找列表中值为x的元素,若存在,则返回位置,否则,返回0 int Search(const T &x); //删除表中第k个元素,并將值赋给x,并返回操作后的列表 SimChain<T>& Delete(int k, T &x); //在第k个位置之后插入元素x,并并返回操作后的列表 SimChain<T>& Insert(int k, const T &x); //输出列表函数 void Output(ostream &out) const; private: int frist; //第一个节点的索引 static SimSpace<T> S; //静态对象存在于共享存储空间,可使所有类型为T的模拟链表共享模拟空间S };
3.2 释放所有节点
析构函数通过调用此Destroy()函数,实现对模拟链表对象的析构。template <class T> void SimChain<T>::Destroy() //释放链表所有节点 { int next; while (frist!=-1) //frist不是最后一个节点 { next = S.node[frist].link; //指向下一个节点 frist = next; //迭代 } }
3.3 获取链表长度
//返回链表长度 template <class T> int SimChain<T>::Length() const { int current = frist; //当前节点指向首节点 int len = 0; //元素计数 while (current!=-1) //当前节点不是最后一个节点 { current = S.node[current].link; //指向当前节点的下一个节点 len++; } return len; }
3.4 寻找第k个位置的元素
寻找第k个位置的元素,若存在,则将值赋给x,并返回true;否则,返回false//寻找第k个位置的元素,若存在,则将值赋给x,并返回true;否则,返回false template <class T> bool SimChain<T>::Find(int k, T &x) const { if (k > 0) { int current = frist; //获取当前节点 int index = 1; //节点索引值 while (index < k && current != -1) //移至第k个节点,且不为最后一个节点 { current = S.node[current].link; index++; } x = S.node[current].data; return true; } else return false; }
3.5 寻找列表中值为x的元素
寻找列表中值为x的元素,若存在,则返回位置,否则,返回0//寻找列表中值为x的元素,若存在,则返回位置,否则,返回0 template <class T> int SimChain<T>::Search(const T &x) { int current = frist; //获取当前位置 while (current != -1) //未到末节点 { if (x == S.node[current].data) return current+1; current = S.node[current].link; //指向下一节点 } return 0; }
3.6 删除表中第k个元素
删除表中第k个元素,并將值赋给x,并返回操作后的列表//删除表中第k个元素,并將值赋给x,并返回操作后的列表 template <class T> SimChain<T>& SimChain<T>::Delete(int k, T &x) { if (k < 1 || frist == -1) //不存在第k个元素 throw OutOfRange(); else { if (k == 1) //删除第一个节点 { x = S.node[k-1].data; //将首节点元素赋给x frist = S.node[k-1].link; //将下一节点作为首节点,即删除首节点 } else { int index = 1; //索引值 int current = frist; while (index < k - 1 && current != -1) //移至第k-1个位置 { current = S.node[current].link; //指向下一个节点 index++; } if (current == -1 || S.node[current].link == -1) throw OutOfRange(); int p = S.node[current].link; //指向第k个节点 x = S.node[p].data; //获取第k个元素值 S.node[current].link = S.node[p].link; //删除第k个元素 S.Deallocate(p); //释放空间 } } return *this; }
3.7 在第k个位置之后插入元素x
在第k个位置之后插入元素x,并返回操作后的列表//在第k个位置之后插入元素x,并返回操作后的列表 template <class T> SimChain<T>& SimChain<T>::Insert(int k, const T &x) { if (k < 0) throw OutOfRange(); int current = frist; //获取当前位置 int index = 1; //索引值 while (current!=-1 && index<k) //移动到第k个节点 { current = S.node[current].link; //指向下一节点 index++; } if (k>0 && current == -1) //不是在首节点插入,当前指针不能为末节点 throw OutOfRange(); int after = S.node[current].link; //指向原来的第k+1个节点 int p = S.Allocate(); //分配一个新节点 S.node[p].data = x; //给新节点赋值 if (k) //不是首节点 { S.node[current].link = p; //原来第k个节点指向分配的新节点 S.node[p].link = after; //新分配的节点指向原来的第k+1个节点 } else //首节点 { S.node[p].link = frist; frist = p; } return *this; }
3.8 输出模拟链表
通过重载运算符”<<”实现。//输出链表函数 //重载运算符 "<<" template <class T> inline ostream &operator <<(ostream &out, SimChain<T> &S) { S.Output(out); return out; } template <class T> void SimChain<T>::Output(ostream &out) const { int current = frist; while (current != -1) { cout << S.node[current].data << " "; current = S.node[current].link; } }
4. 测试样例
//模拟链表 SimChain<int> S; S.Insert(0, 1); cout <<"S.Insert(0, 1): "<< S << endl<<endl; S.Insert(1, 5); cout << "S.Insert(1, 5): " << S << endl << endl; for (int i = 2; i < 7; i++) S.Insert(i, i); cout << "测试Insert()函数: " << S << endl << endl; int x; S.Delete(3, x); cout << "测试Delete()函数,删除中间元素: " << S <<" "<<x<< endl << endl; S.Delete(1, x); cout << "测试Delete()函数,删除首元素: " << S << " " << x << endl << endl; S.Delete(S.Length(), x); cout << "测试Delete()函数,删除末元素: " << S << " " << x << endl << endl; bool find; find=S.Find(1, x); cout << "测试Find()函数,寻找首元素: " << find << " " << x << endl << endl; find = S.Find(0, x); cout << "测试Find()函数,寻找位置为0元素: " << find << " " << x << endl << endl; find = S.Find(S.Length(), x); cout << "测试Find()函数,寻找末元素: " << find << " " << x << endl << endl; cou cb33 t << "测试Search()函数: " << S.Search(5) << endl << endl;
参考文献:
[1] 数据结构算法与应用:C++描述(Data Structures, Algorithms and Applications in C++ 的中文版)
相关文章推荐
- 数据结构与算法(Java描述)-5、循环链表仿真链表以及循环链表应用
- 数据结构与算法分析:C++描述(Mark Allen Weiss) 和 数据结构(刘大有)笔记
- C++队列模拟银行排队叫号(加州大学伯克利分校计算机专业数据结构与算法作业)
- 数据结构与算法C++描述(12)---堆及最大堆
- 数据结构(java语言描述)链表的使用
- 【数据结构】单链表插入算法
- 数据结构——c语言描述 第二章(3) 双向链表
- 数据结构与算法学习笔记之写链表代码的正确姿势(下)
- 数据结构之单循环链表C++(模板)
- 数据结构与算法(4)---Java语言实现:队列的单链表定义
- c++ 数据结构 用单链表实现多项式的类定义
- c/c++常用算法(1) -- 数据结构(线性表的顺序存储)
- 数据结构基础算法-循环链表
- 数据结构作业代码保存-2.1 单向循环链表的建立,插入和删除,和指针移动
- Java数据结构与算法(四)-链表
- 数据结构与算法:链表基础
- 数据结构_7:图算法 :c++/STL
- 数据结构与算法的js描述总结
- (摘)面向对象c++数据结构之基本数据结构-链表-使用链表管理器(连载中)
- 数据结构之堆栈模拟应用(算法3.1)