代码开始前的闲谈
1.本章在基础的顺序表功能上增加了 循环移动k位的函数、约瑟夫问题的求解函数,合并两个顺序表的函数。
2 .如果线性表 首先重载了 cout<<,线性表的元素也重载了cout<<。.cout <<多次重载 可以用 static 或者 inline 来限制文件作用域 就不会 报重复定义的错了。
包括的主要知识点
1.间接寻址方式顺序表的书写。
2.循环移动k位的算法。
3.约瑟夫问题的求解函数。
运行结构截图
头文件
#pragma once #define MaxSize 100 #include<ostream> #include<iostream> #include<cstdlib> #include<cstring> using namespace std; template<class T> class LinearList; template<class T> ostream& operator<<(ostream & os, LinearList<T> & a); template<typename T> void PrintList2(LinearList<T> & a); typedef struct student { int ID; char name[40]; friend ostream & operator<<(ostream & out, struct student & data) { out << "student ID:"; out << data.ID; out << " name:"; out << data.name; out << endl; return out; } }student; template<class T> class LinearList { public: LinearList();//无参数构造函数。 LinearList(int maxSize); LinearList(T a[], int n);//n个数据的 构造函数。 LinearList(const LinearList& a);//深拷贝构造函数 ~LinearList();//析构函数。 private: T **Data;// int Length;//总容量。 int Size;//当前容量。 public: int GetLength();//获取线性表储存数据的个数。 int GetSize();//获取顺序表总分配空间。 T GetPos(int pos);//返回线性表的 第 pos 个数据。 void InsertObjInPos(T Obj, int pos);//在第 pos 个位置 插入Obj T DeletePos(int pos);//删除第 pos 个位置的数据。 int Locate(T Obj);//查找 数据Obj 的位置。没有则返回 -1。 void PrintList1(); friend ostream& operator<< <>(ostream & os, LinearList<T>& a);//重载输出线性表 friend void PrintList2<>(LinearList<T> & a);//友元函数输出顺序表。 T SetPosToObj(int pos, T Obj);//把第 pos 个位置的数据改成 Obj T *ToFirstAdd();//返回线性表首地址 void SetLength(int len);//设置线性表长度。 void RevListSeg(int form, int to);//从 form 到 to 位 倒置。 void LeftRotate(int k);//数据循环左移 k 位。 void Josephus(int m);//报数到 m 的人出圈。 LinearList<T> & operator =(const LinearList<T> & a);//深拷贝。 }; template<typename T> ostream& operator<<(ostream & os, LinearList<T> & a) { for (int i = 0; i < a.Length; i++) { os << *(a.Data[i]) << " "; } os << '\n'; return os; } template<typename T> void PrintList2(LinearList<T> & a) { for (int i = 0; i < a.Length; i++) { std::cout << *(a.Data[i]) << " "; } std::cout << '\n'; }
源文件
#include "stdafx.h" #include "LinearList.h" template<typename T> LinearList<T>::LinearList() { Length = 0; Size = 5; Data = new T*[5]; } template<class T> LinearList<T>::LinearList(int maxSize) { Length = 0; Size = 10; Data = new T*[maxSize]; } template<typename T> LinearList<T>::LinearList(T a[], int n) { this->Length = n; this->Size = n; this->Data = new T*[n]; if (this->Data == nullptr) { throw "LinearList (T a[] , int n) trapped!\n"; } for (int i = 0; i < n; i++) { this->Data[i] = new T; *(this->Data[i]) = a[i]; } } template<typename T> LinearList<T>::LinearList(const LinearList & a) { this->Length=a.Length; this->Size=a.Size; this->Data = new T*[a.Size]; for (int i = 0; i < this->Length; i++) { this->Data[i] = new T; *(this->Data[i])=*(a.Data[i]); } } template<typename T> LinearList<T>::~LinearList() { for (int i = 0; i < Length; i++) { delete [] (this->Data[i]); } delete [] this->Data; Length = 0; } template<typename T> int LinearList<T>::GetLength() { return this->Length; } template<class T> int LinearList<T>::GetSize() { return Size; } template<typename T> T LinearList<T>::GetPos(int pos) { return *(this->Data[pos]); } template<typename T> void LinearList<T>::InsertObjInPos(T Obj, int pos) { if (pos > Length + 1 || pos<1) { throw "InsertObjInPos error! And mostly the position is too long or too short"; return; } this->Length++; if(Length > Size) { Size += 10; this->Data = (T **)realloc(this->Data, Size * sizeof(T)); if (this->Data == nullptr) { //throw exception(); throw "InsertObjInPos error! And mostly wrong in realloc"; } } T * temp=this->Data[Length - 1] = new T; *temp = Obj; for (int i = Length - 1; i >= pos; i--) { this->Data[i] = this->Data[i - 1]; } this->Data[pos - 1] = temp; } template<typename T> T LinearList<T>::DeletePos(int pos) { if (pos<1 || pos>this->Length) { throw "DeletePos error and mostly the position is wrong"; } T temp = *(this->Data[pos - 1]); T *p = this->Data[pos - 1]; for (int i = pos - 1; i < Length - 1; i++) { this->Data[i] = this->Data[i + 1]; } delete p; this->Data[Length - 1] = nullptr; Length--; return temp; } template<typename T> int LinearList<T>::Locate(T Obj) { int pos = -1; for (int i = 0; i < Length; i++) { if (*(this->Data[i]) == Obj) { //return i+1; pos = i + 1; return pos; } } return pos; } template<typename T> void LinearList<T>::PrintList1() { for (int i = 0; i < this->Length; i++) { std::cout << *(this->Data[i]) << ' '; } std::cout << endl; } template<typename T> T LinearList<T>::SetPosToObj(int pos, T Obj) { if (pos<1 || pos>this - Length + 1) { throw "DeletePos error and mostly the position is wrong"; } if (pos == Length + 1) { Length++; this->Data[Length - 1] = new T; *(this->Data[pos - 1]) = Obj; } *(this->Data[pos - 1]) = Obj; return T(); } template<typename T> T * LinearList<T>::ToFirstAdd() { return this->Data[0]; } template<typename T> void LinearList<T>::SetLength(int len) { this->Length = len; } template<typename T> void LinearList<T>::RevListSeg(int form, int to) { if (form < 1 || form>Length || to<1 || to>Length) { throw "RevListSeg() error!"; } T *temp; for (int i = 0; i <= (to - form) / 2; i++) { temp = Data[form - 1 + i]; Data[form - 1 + i] = Data[to - 1 - i]; Data[to - 1 - i] = temp; } } template<class T> void LinearList<T>::LeftRotate(int k) { RevListSeg(1, k); RevListSeg(k + 1, Length); RevListSeg(1, Length); } template<class T> void LinearList<T>::Josephus(int m) { int s = 0;//出圈的位置。 for (int n = Length; n >= 2; n--) { s = (s + m-1) % n; cout << "After delete " << *Data[s]<<": "; DeletePos(s+1); cout << *this; } cout << "delete position " << m << " the result is " << *this; } template<typename T> LinearList<T> & LinearList<T>::operator=(const LinearList<T> & a) { if (this->Length != 0) { for (int i = 0; i < Length; i++) { delete[] this->Data[i]; } delete[] this->Data; } this->Length = a.Length; this->Size = a.Size; this->Data = new T*[a.Size]; for (int i = 0; i < this->Length; i++) { this->Data[i] = new T; *(this->Data[i]) = *(a.Data[i]); } return *this; }
用于测试的主函数
// 线性表_间接寻址.cpp : 定义控制台应用程序的入口点。 #include "stdafx.h" #include"LinearList.cpp" //#include"Student.h" #include<iostream> using namespace std; int main() { int test[10] = { 2,4,6,8,10,12,14,16,18,20 }; LinearList<int> a(test, 10); std::cout << "构造函数后顺序表为:" << endl; a.PrintList1();//第一种方法输出。 std::cout << "在第1个位置插入99" << endl; a.InsertObjInPos(99, 1); PrintList2(a);//第二种方法输出。 std::cout << "在第12个位置插入88" << endl; a.InsertObjInPos(88, 12); cout << a;//重载输出。 std::cout << "查找 数据 3 的位置:" << a.Locate(3) << endl; std::cout << "查找到数据 4 并删除后输出:"; a.DeletePos(a.Locate(4)); cout << a;//再来一个重载输出。其实重载输出还有其他的写法。我这里用了 <> 来写。下一章我会用其他的写法实现重载。 cout << "输出顺序表数组首地址元素:"; std::cout << a.ToFirstAdd()[0]<< endl; cout << "倒置 2-6位后:"; a.RevListSeg(2, 6); cout<<a; cout << "循环左移 3 位后:"; a.LeftRotate(3); cout << a; cout << endl << " 另一个顺序表:"; int test2[10] = { 1,2,3,4,5,6,7,8,9,10 }; LinearList<int> b(test2, 8); cout << b; cout << "报数到 3 的出圈:"; b.Josephus(3); cout << "拷贝 a 表 到 c 表 :"; LinearList<int> c(a); cout << a; cout << "operator = 拷贝c:"; LinearList<int> d; d = c; cout << d; cout << "operator = 拷贝b:"; d = b; cout << d; cout << "元素为两个学生结构的线性表:"; student e[3]; e[0].ID=111; e[1].ID=222; e[2].ID=333; strcpy_s(e[0].name, 40, "aaa"); strcpy_s(e[1].name, 40, "bbb"); strcpy_s(e[2].name, 40, "ccc"); LinearList<student> f(e, 2); cout << f; cout << "在第三个位置插入一个学生结构:"<<endl; f.InsertObjInPos(e[2], 3); cout << f; cout << "删除第二个元素:"<<endl; f.DeletePos(2); cout << f; getchar(); return 0; }