代碼開始前的閒談
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;
}