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


猜你喜欢

转载自blog.csdn.net/wang_huizhang/article/details/72670079