C++_009_數據結構_線性表_間接尋址方式儲存

代碼開始前的閒談

    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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章