顺序表
【1】线性结构
在数据元素的非空有限集中,线性结构特点:
a. 存在唯一的一个被称作“第一个”的数据元素
b. 存在唯一的一个被称作“最后一个”的数据元素
c. 除第一个之外,集合中的每个数据元素均只有一个前驱
d. 除最后一个之外,集合中每个数据元素均只有一个后继
【2】线性表
线性表是最常用且简单的一种数据结构。
一个线性表是n个数据元素的有限序列。
线性表中的数据元素可以是各种各样的,但同一线性表中的元素必定具有相同特性。
在复杂的线性表中,一个数据元素可以由若干个数据项组成。这种情况下,常把数据元素称为记录。
而含大量记录的线性表称为文件。
【3】顺序表
线性表的顺序表示指用一组地址连续的存储单元依次存储线性表的数据元素。
线性表的顺序存储结构如下:
【4】顺序表的优缺点
优点:乐于随机存取。
因为物理结构和逻辑结构均连续,所以数据存取尤其简易。
缺点:悲在插入删除
为了保证存储的连续性,插入或删除会比较麻烦。
另外一点:顺序存储要求明确数据的规模用来分配给数据空间。
【5】C++实现顺序表代码
<1>SeqList.h文件
1 #include <iostream> 2 #include <assert.h> 3 #include <typeinfo.h> 4 #include <string.h> 5 using namespace std; 6 7 #define UM_QUIT 0 8 #define UM_INPUTR 1 9 #define UM_PRINT 2 10 #define UM_INPUTH 3 11 #define FINDVALUE 4 12 #define UM_INSERT 5 13 #define UM_REMOVE 6 14 #define UM_SORT 7 15 #define UM_REMOVEALL 8 16 #define UM_REVERSE 9 17 #define UM_ERASE 10 18 #define UM_PVPOS 11 19 20 #define MAXSIZE 10 21 #define INCSIZE 5 22 23 template <class Type> 24 class SeqList 25 { 26 private: 27 Type* m_pData; //数据区域 28 size_t m_nMaxSize; //最大容量 29 size_t m_nLen; //元素个数 30 31 public: 32 SeqList(size_t size = MAXSIZE); 33 SeqList(const SeqList<Type>& sqList); 34 SeqList<Type>& operator=(const SeqList<Type>& sqList); 35 ~SeqList(); 36 37 public: 38 size_t GetMaxSize() const; 39 void SetMaxSize(size_t nMaxSize) const; 40 size_t GetLength() const; 41 void SetLength(size_t nLen) const; 42 43 public: 44 bool IsFull() const; 45 bool IsEmpty() const; 46 bool IsElement(const Type& Value); 47 void Push_Back(const Type& Value); 48 void Push_Front(const Type& Value); 49 void At(const size_t pos); 50 size_t FindPos(const Type& Value); 51 void Insert(const size_t pos, const Type& Value); 52 void Remove(const Type& Value); 53 void Erase(const size_t pos); 54 void RemoveAll(const Type& Value); 55 void Sort(); 56 void Reverse(); 57 void Print() const; 58 59 private: 60 bool IncSize(); 61 void Swap(const size_t leftpos, const size_t rightpos); 62 }; 63 //基本属性函数 64 template <class Type> 65 size_t SeqList<Type>::GetMaxSize() const 66 { 67 return m_nMaxSize; 68 } 69 template <class Type> 70 void SeqList<Type>::SetMaxSize(size_t nMaxSize) const 71 { 72 m_nMaxSize = nMaxSize; 73 } 74 template <class Type> 75 size_t SeqList<Type>::GetLength() const 76 { 77 return m_nLen; 78 } 79 template <class Type> 80 void SeqList<Type>::SetLength(size_t nLen) const 81 { 82 m_nLen = nLen; 83 } 84 // 作用:扩充顺序表容量 85 // 当数据数量大于最大容量时,为顺序表增加容量 86 // 增加度量为INCSIZE 87 template <class Type> 88 bool SeqList<Type>::IncSize() 89 { 90 Type* pNewDate = new Type[m_nMaxSize + INCSIZE + 1]; 91 if (NULL == pNewDate) 92 return false; 93 memcpy(pNewDate, m_pData, sizeof(Type) * (m_nLen + 1)); 94 m_pData = pNewDate; 95 m_nMaxSize += INCSIZE; 96 return true; 97 } 98 //交换数据 99 template <class Type> 100 void SeqList<Type>::Swap(const size_t leftpos, const size_t rightpos) 101 { 102 Type temp = m_pData[leftpos]; 103 m_pData[leftpos] = m_pData[rightpos]; 104 m_pData[rightpos] = temp; 105 } 106 //默认复合构造函数 107 template <class Type> 108 SeqList<Type>::SeqList(size_t size = MAXSIZE) 109 { 110 m_nMaxSize = size > MAXSIZE ? size : MAXSIZE; 111 m_pData = new Type[m_nMaxSize + 1]; 112 assert(m_pData != NULL); 113 m_nLen = 0; 114 } 115 //拷贝构造函数 116 template <class Type> 117 SeqList<Type>::SeqList(const SeqList<Type>& sqList) 118 { 119 if (this != &sqList) 120 { 121 m_pData = new Type[sqList.m_nMaxSize + 1]; 122 if (m_pData != NULL) 123 { 124 memcpy(m_pData, sqList.m_pData, sizeof(Type) * (sqList.m_nLen + 1)); 125 } 126 m_nMaxSize = sqList.m_nMaxSize; 127 m_nLen = sqList.m_nLen; 128 } 129 } 130 //赋值函数(思考什么时候调用赋值函数) 131 template <class Type> 132 SeqList<Type>& SeqList<Type>::operator=(const SeqList<Type>& sqList) 133 { 134 m_nLen = sqList.m_nLen; 135 m_nMaxSize = sqList.m_nMaxSize; 136 memcpy(m_pData, sqList.m_pData, sizeof(Type) * (sqList.m_nLen + 1)); 137 return *this; 138 } 139 //析构函数 140 template <class Type> 141 SeqList<Type>::~SeqList() 142 { 143 if (m_pData != NULL) 144 { 145 delete []m_pData; 146 m_pData = NULL; 147 } 148 m_nMaxSize = 0; 149 m_nLen = 0; 150 } 151 //判满 152 template <class Type> 153 bool SeqList<Type>::IsFull() const 154 { 155 return m_nLen == m_nMaxSize; 156 } 157 //判空 158 template <class Type> 159 bool SeqList<Type>::IsEmpty() const 160 { 161 return 0 == m_nLen; 162 } 163 //是否是顺序表中元素 164 template <class Type> 165 bool SeqList<Type>::IsElement(const Type& Value) 166 { 167 size_t pos = FindPos(Value); 168 return 0 != pos; 169 } 170 //从顺序表末尾添加元素 171 template <class Type> 172 void SeqList<Type>::Push_Back(const Type& Value) 173 { 174 if (IsFull() && !IncSize()) //注意写法用意 175 return; 176 m_pData[++m_nLen] = Value; 177 } 178 //从顺序表首部添加元素 179 template <class Type> 180 void SeqList<Type>::Push_Front(const Type& Value) 181 { 182 if (IsFull() && !IncSize()) 183 return; 184 for (size_t i = m_nLen; i > 0; --i) 185 { 186 m_pData[i + 1] = m_pData[i]; 187 } 188 ++m_nLen; 189 m_pData[1] = Value; 190 } 191 //输出对应索引处的数据 192 template <class Type> 193 void SeqList<Type>::At(const size_t pos) 194 { 195 if (pos <= 0 || pos > m_nLen) 196 cout << "输入下标有误!" << endl; 197 else 198 cout << pos << "位置的数据为:" << m_pData[pos] << endl; 199 } 200 //查找某数据的索引 201 template <class Type> 202 size_t SeqList<Type>::FindPos(const Type& Value) 203 { 204 m_pData[0] = Value; 205 size_t i = m_nLen; 206 while (m_pData[i] != Value) 207 { 208 --i; 209 } 210 return i; 211 } 212 //在索引处插入值 213 template <class Type> 214 void SeqList<Type>::Insert(const size_t pos, const Type& Value) 215 { 216 if (pos <= 0 || pos > m_nLen + 1) 217 return; 218 if (IsFull() && !IncSize()) 219 return; 220 221 ++m_nLen; 222 for (size_t i = m_nLen; i > pos; --i) 223 { 224 m_pData[i] = m_pData[i-1]; 225 } 226 m_pData[pos] = Value; 227 } 228 //移除某个值 229 template <class Type> 230 void SeqList<Type>::Remove(const Type& Value) 231 { 232 if (IsElement(Value)) 233 { 234 size_t pos = FindPos(Value); 235 Erase(pos); 236 } 237 else 238 { 239 cout << "输入数据不存在!" << endl; 240 } 241 } 242 //按索引删除数据 243 template <class Type> 244 void SeqList<Type>::Erase(const size_t pos) 245 { 246 if (pos <= 0 || pos > m_nLen) 247 { 248 cout << "输入错误" << endl; 249 } 250 else 251 { 252 for (size_t i = pos; i < m_nLen; ++i) 253 { 254 m_pData[i] = m_pData[i+1]; 255 } 256 --m_nLen; 257 cout << "删除成功!删除后结果如下:" << endl; 258 Print(); 259 } 260 } 261 //删除全部(删除所有出现在顺序表中的某值) 262 template <class Type> 263 void SeqList<Type>::RemoveAll(const Type& Value) 264 { 265 if (IsElement(Value)) 266 { 267 for (size_t i = m_nLen; i > 0; --i) 268 { 269 if (m_pData[i] == Value) 270 Remove(Value); 271 } 272 273 cout << "删除全部成功!删除后结果如下:" << endl; 274 Print(); 275 } 276 else 277 { 278 cout << "输入的数据不存在!" << endl; 279 } 280 } 281 //顺序表数据排序 282 template <class Type> 283 void SeqList<Type>::Sort() 284 { 285 if (m_nLen > 2) 286 { 287 size_t i = 0, j = 0; 288 for (i = 2; i <= m_nLen; ++i) 289 { 290 if (m_pData[i] < m_pData[i - 1]) 291 { 292 m_pData[0] = m_pData[i]; 293 j = i - 1; 294 do 295 { 296 m_pData[j + 1] = m_pData[j]; 297 --j; 298 } while(m_pData[j] > m_pData[0]); 299 m_pData[j + 1] = m_pData[0]; 300 } 301 } 302 } 303 } 304 //逆置顺序表 305 template <class Type> 306 void SeqList<Type>::Reverse() 307 { 308 if (m_nLen > 2) 309 { 310 size_t i = 0, j = 0; 311 for (i = 1, j = m_nLen; i < j; ++i, --j) 312 { 313 Swap(i, j); 314 } 315 cout << "逆置结果如下:" << endl; 316 Print(); 317 } 318 } 319 //打印顺序表数据信息 320 template <class Type> 321 void SeqList<Type>::Print() const 322 { 323 cout << "容量:" << m_nMaxSize << endl; 324 cout << "元素的个数:" << m_nLen << endl; 325 cout << "数据如下:" << endl; 326 for (size_t i = 1; i <= m_nLen; ++i) 327 { 328 cout << m_pData[i] << " "; 329 } 330 cout << endl; 331 }
<2>TestSeqList.cpp文件
1 #include "SeqList.h" 2 using namespace std; 3 4 void main() 5 { 6 cout << "\t**********************深拷贝************************\t\t\t\t" << endl; 7 SeqList<int> MylistA; 8 MylistA.Push_Back(12); 9 MylistA.Push_Back(23); 10 MylistA.Push_Back(34); 11 cout << "打印MylistA数据信息:" << endl; 12 MylistA.Print(); 13 SeqList<int> YoulistA(MylistA); 14 cout << "打印YoulistA数据信息:" << endl; 15 YoulistA.Print(); 16 17 cout << "\t**********************赋值功能************************\t\t\t\t" << endl; 18 SeqList<int> MylistB, YoulistB; 19 MylistB.Push_Front(10); 20 MylistB.Push_Front(11); 21 MylistB.Push_Front(12); 22 cout << "打印MylistB数据信息:" << endl; 23 MylistB.Print(); 24 YoulistB = MylistB; 25 cout << "打印YoulistB数据信息:" << endl; 26 YoulistB.Print(); 27 28 cout << "测试顺序表实现:" << endl; 29 SeqList<int> mylist; 30 int select = 1; 31 int item = 0; 32 size_t pos = 0; 33 while (select != 0) 34 { 35 cout << "\t********************菜单*************************\t\t\t\t" << endl; 36 cout << "\t\t* 1.输入数据r 2.打印数据 *\t\t\t\t" << endl; 37 cout << "\t\t* 3.输入数据h 4.按值查询 *\t\t\t\t" << endl; 38 cout << "\t\t* 5.插入数据 6.删除数据 *\t\t\t\t" << endl; 39 cout << "\t\t* 7.排序 8.全部删除 *\t\t\t\t" << endl; 40 cout << "\t\t* 9.逆置 10.位置删除 *\t\t\t\t" << endl; 41 cout << "\t\t* 11.查询位置值 0.退出 *\t\t\t\t" << endl; 42 cout << "\t**********************************************\t\t\t\t" << endl; 43 cout << "请选择操作:" <<endl; 44 cin >> select; 45 switch (select) 46 { 47 case UM_QUIT: //0 48 break; 49 case UM_INPUTR: //1 50 cout << "请输入数据并以-1结束" << endl; 51 while (cin >> item, item != -1) 52 { 53 mylist.Push_Back(item); 54 } 55 break; 56 case UM_PRINT: //2 57 mylist.Print(); 58 break; 59 case UM_INPUTH: //3 60 cout << "请输入数据并以-1结束" << endl; 61 while (cin>>item, item != -1) 62 { 63 mylist.Push_Front(item); 64 } 65 break; 66 case FINDVALUE: //4 67 cout << "请输入查询的数据 " << endl; 68 cin >> item; 69 pos = mylist.FindPos(item); 70 if (0 == pos) 71 { 72 cout << "查无此数据" << endl; 73 } 74 else 75 { 76 cout << "数据的下标是: " << pos << endl; 77 } 78 break; 79 case UM_INSERT: //5 80 cout << "请输入插入的数据和位置信息" << endl; 81 cin >> item >>pos; 82 mylist.Insert(pos, item); 83 mylist.Print(); 84 break; 85 case UM_REMOVE: //6 86 cout << "请输入删除的数据" << endl; 87 cin >> item; 88 mylist.Remove(item); 89 break; 90 case UM_SORT: //7 91 mylist.Sort(); 92 break; 93 case UM_REMOVEALL: //8 94 cout << "请输入数据:" << endl; 95 cin >> item; 96 mylist.RemoveAll(item); 97 break; 98 case UM_REVERSE: //9 99 mylist.Reverse(); 100 break; 101 case UM_ERASE: //10 102 cout << "请输入位置信息:" << endl; 103 cin >> pos; 104 mylist.Erase(pos); 105 break; 106 case UM_PVPOS: //11 107 cout << "请输入位置信息:" << endl; 108 cin >> pos; 109 mylist.At(pos); 110 break; 111 default: 112 cout << "选择错误,请重新选择" << endl; 113 } 114 } 115 }
备注:以上实现代码当时运行环境为VS2010
为什么模板类的.h文件与模板类的.cpp文件没有像普通类那般分离开,请参见随笔《模板类 声明与定义》。
Good Good Study, Day Day Up.
顺序 选择 循环 总结