数据可以用不同的形式进行描述或存储在计算机存储器中。最常见的数据描述方法有:公式化描述、链接描述、间接寻址和模拟指针。
公式化描述借助数学公式来确定元素表中的每个元素分别存储在何处(如存储器地址) 。最简单的情形就是把所有元素依次连续存储在一片连续的存储空间中,这就是通常所说的连续线性表。
在链接描述中,元素表中的每个元素可以存储在存储器的不同区域中,每个元素都包含一个指向下一个元素的指针。同样,在间接寻址方式中,元素表中的每个元素也可以存储在存储器的不同区域中,不同的是,此时必须保存一张表,该表的第 i项指向元素表中的第 i个元素,所以这张表是一个用来存储元素地址的表。
在公式化描述中,元素地址是由数学公式来确定的;在链接描述中,元素地址分布在每一个表元素中;而在间接寻址方式下,元素地址则被收集在一张表中。
模拟指针非常类似于链接描述,区别在于它用整数代替了 C + +指针,整数所扮演的角色与指针所扮演的角色完全相同。
数据结构( data structure)包括数据对象和实例以及构成实例的每个元素之间所存在的各种关系。这些关系可由相关的函数来实现。 当我们研究数据结构时,关心的是数据对象(实际上是实例)的描述以及与数据对象相关函数的具体实现。数据对象的良好描述可以有效地促进函数的高效实现。
线性表
线性表( linear list)是这样的数据对象,其实例形式为: (e1 , e2 ,... en ),其中 n 是有穷自然
数。 ei是表中的元素, n 是表的长度。元素可以被视为原子,因为它们本身的结构与线性表的结构无关。当 n = 0 时,表为空;当 n > 0 时, e1是第一个元素, en 是最后一个元素,可以认为 el优先于 e2, e2 优先于 e3,如此等等。除了这种优先关系之外,在线性表中不再有其他的结构。
1 公式化描述
公式化描述( f o r m a l a - b a s e d)采用数组来表示一个对象的实例,数组中的每个位置被称之为单元( c e l l)或节点( n o d e),每个数组单元应该足够大,以便能够容纳数据对象实例中的任意一个元素。在某些情况下,每个实例可分别用一个独立的数组来描述,而在其他情况下,可能要使用一个数组来描述几个实例。实例中每个元素在数组中的位置可以用一个数学公式来指明。假定使用一个数组来描述表,需要把表中的每个元素映射到数组的具体位置上。
l o c a t i on (i )= i - 1
代码实现:
1 #ifndef LINEARLIST_H 2 #define LINEARLIST_H 3 #include<iostream> 4 #include<cstdlib> 5 #include<new> 6 using std::cout; 7 using std::endl; 8 template<class T> 9 class LinearList 10 { 11 public: 12 LinearList(int MaxListSize=10);//构造函数 13 virtual ~LinearList(); 14 bool IsEmpty()const 15 { 16 return length==0; 17 } 18 int Length()const {return length;} 19 bool Find(int k,T& x)const;//返回第K个元素到中 20 int Search(T& x)const;//返回x的位置 21 LinearList<T>& Delete(int k,T& x);//删除位置k的元素,并将元素值存到x 22 LinearList<T>& Insert(int k,const T& x);//将x插入到k位置之后 23 void Output(std::ostream& out)const;//输出到流 24 25 protected: 26 private: 27 int length;//线性表当前长度 28 int MaxSize;//最大长度 29 T *element;//线性表数组 30 }; 31 32 class NoMem 33 { 34 public : 35 NoMem(){ 36 cout<<"No Memory"<<endl; 37 //std::exit(1); 38 } 39 40 }; 41 42 class OutofBounds 43 { 44 public : 45 OutofBounds() 46 { 47 cout<<"Out of Bounds"<<endl; 48 //std::exit(1); 49 } 50 }; 51 52 53 void my_new_handler() 54 { 55 throw NoMem(); 56 } 57 58 template<class T> 59 LinearList<T>::LinearList(int MaxListSize) 60 { 61 std::new_handler old_Handler=std::set_new_handler(my_new_handler); 62 MaxSize=MaxListSize; 63 element=new T[MaxSize]; 64 length=0; 65 66 } 67 68 template<class T> 69 LinearList<T>::~LinearList() 70 { 71 delete[]element; 72 MaxSize=0; 73 length=0; 74 } 75 76 template<class T> 77 bool LinearList<T>::Find(int k,T&x)const 78 { 79 if(k<0||k>length) 80 return false; 81 x=element[k-1]; 82 return true; 83 } 84 85 template<class T> 86 int LinearList<T>::Search(T &x)const 87 { 88 int i=0; 89 while(i<length&&element[i]!=x) 90 { 91 i++; 92 } 93 if(i==length) return 0; 94 else return i+1; 95 } 96 97 template<class T> 98 LinearList<T>& LinearList<T>::Delete(int k,T &x) 99 { 100 if(Find(k,x))//存在位置k 101 { 102 for(int i=k;i<length;++i) 103 { 104 element[i-1]=element[i];//k之后元素向前移动一位 105 } 106 length--; 107 return *this; 108 } 109 else 110 { 111 throw OutofBounds(); 112 } 113 } 114 115 template<class T> 116 LinearList<T>& LinearList<T>::Insert(int k,const T &x) 117 { 118 if(k<0||k>length) 119 { 120 throw OutofBounds(); 121 } 122 else if(length==MaxSize) 123 { 124 throw NoMem(); 125 } 126 else 127 { 128 for(int i=length;i>k;--i) 129 { 130 element[i]=element[i-1];//k之后元素向后移动一位 131 } 132 element[k]=x; 133 length++; 134 return *this; 135 } 136 } 137 138 template<class T> 139 void LinearList<T>::Output(std::ostream& out)const 140 { 141 for(int i=0;i<length;i++) 142 { 143 144 out<<element[i]<<" "; 145 } 146 } 147 148 template<class T> 149 std::ostream& operator<<(std::ostream &out,const LinearList<T>& x) 150 { 151 x.Output(out); 152 return out; 153 } 154 155 #endif // LINEARLIST_H