第十八章练习一:稀疏数组

来源:互联网 发布:a* b*算法 编辑:程序博客网 时间:2024/06/07 18:03


解析:

1、稀疏数组:一个数组中绝大多数元素的值都是同一个值(比如为0或者1等),只有极少部分(稀少)为相互相异的其它值。

      比如a[100]数组中,有95个元素都是1,只有5个元素分别为2,3,5,7,9,那么这样的数组称为稀疏数组。因此,我们只关心极少部分的元素。


2、构建一个类模板,这个模板是一个链表结构,分别装入节点的头部和尾部,节点为私有成员类,节点装入索引、数据、及上下指向。


3、主程序中,须创建20个随机数,这20个随机数作为索引,范围是0到499,因此是不相同的,即须生成20个500范围内的不重复的随机数。


4、节点的赋值用在[]重载中,要考虑这个节点插入的情况,如果在链表中间、头部、尾部、空链等情况。


5、为了节约代码量,用了两个功能成员函数copyfrom和freememory。


代码如下:

#include <iostream>#include<ctime> #include <stdexcept>using namespace std;template<typename T>class SparseArray{public:SparseArray():pFirst(0),pLast(0){}SparseArray(const SparseArray& array);~SparseArray();SparseArray& operator=(const SparseArray& array);T& operator[](int index);void show(); //为了减少代码量,用copy和freememory成员替代相关功能 void copyfrom(const SparseArray& array);void freeMemory();private:class Node{public:int index;T* pObject;Node* pNext;Node* pPrevious;Node(int newIndes):index(newIndes),pObject(new T),pNext(0),pPrevious(0){}Node(const Node& node):index(node.index),pObject(*node.pObject),pNext(0),pPrevious(0){}~Node(){delete pObject;}};Node* pFirst;Node* pLast;};template<typename T>void SparseArray<T>::copyfrom(const SparseArray& array){if(array.pFirst){//源链表不空 pFirst=pLast=new Node(*array.pFirst);Node* pCurrent=array.pFirst;  //源链表移动替身 Node* pTemp=0;while(pCurrent=pCurrent->pNext){pTemp=pLast;pLast=new Node(*pCurrent);pTemp->pNext=pLast;pLast->pPrevious=pTemp;}}elsepFirst=pLast=0;//若空,目标链也为空 } template<typename T>void SparseArray<T>::freeMemory(){Node* pCurrent=pFirst;Node* pTemp=0;while(pCurrent){pTemp=pCurrent->pNext;delete pCurrent;pCurrent=pTemp;}}template<typename T>SparseArray<T>::SparseArray(const SparseArray& array){copyfrom(array);}template<typename T>SparseArray<T>::~SparseArray(){freeMemory();}template<typename T>SparseArray<T>& SparseArray<T>::operator=(const SparseArray& array){if(this==&array)return *this;freeMemory();copyfrom(array);return *this;}template<typename T>T& SparseArray<T>::operator[](int index){if(index<0) throw std::out_of_range("rang wrong!");//搜索节点,有意按index递增情况,如果没有,下步将建立它     Node* pCurrent=pFirst;while(pCurrent){if(pCurrent->index == index) return *pCurrent->pObject;//有,返回 if(pCurrent->index > index)  break;//递增方向超过索引,中断,下步将新建节点并插进 pCurrent = pCurrent->pNext;}// 新建节点并插入 Node* pNode = new Node(index);pNode->pObject = new T;//分配好内存,主程序直接是赋值 if(pCurrent) {                         //非链表尾部跳出,则插入新节点.即链表中间插入 if(pCurrent->pPrevious) {//非链表头部 pCurrent->pPrevious->pNext = pNode;//左节点指向新节点 pNode->pPrevious = pCurrent->pPrevious;//新节点回指左节点 pCurrent->pPrevious = pNode;//当前节点回指新节点 pNode->pNext = pCurrent;//新节点指向当前节点 }else{                //链表头 pNode->pNext = pCurrent;//新节点指当前 pCurrent->pPrevious = pNode;//当前回指新节点 pFirst = pNode;//更新头部 }} else {                         if(pLast) {//链表尾部跳出,直接屁股追加一节点 pLast->pNext = pNode;//尾节点指向新节点 pNode->pPrevious = pLast;//新节点回指原尾节点 pLast = pNode;//更新尾部 }else //空表情况 pFirst = pLast = pNode;}return *pNode->pObject;//返回新建节点值 }template<typename T>void SparseArray<T>::show(){Node* pCurrent=pFirst;while(pCurrent){cout<<"["<<pCurrent->index<<"]"<<*pCurrent->pObject<<endl;pCurrent=pCurrent->pNext;}}
int randomN(int count){return static_cast<int>((count*static_cast<long>(rand()))/(RAND_MAX+1));}int main(int argc, char *argv[]){SparseArray<int> numbers;srand((unsigned)time(0));const int count=20;int indexes[count];int index=0;for(int i=0;i<count;i++){//产生20元素 for(;;){index=randomN(500);//产生每元素值 indexes[i]=index;//依次保存每元素 for(int j=0;j<i-1;j++){if(index==indexes[j]){//跟以前全部元素比较 index=-1;break;//相同跳出,请重新产生 }}if(index>=0) break;//相异,不再重新产生,跳出 }numbers[index]=32+randomN(181);}numbers.show();return 0;}