数组和链表描述线性表

数组描述线性表

#pragma warning(disable:4996)
#include <iostream>
#include<iterator>
#include<algorithm>
using namespace std;
//边长一维数组(增加或减少)
//改变一个一维数组的长度
template<class T>
void changeLength1D(T*& a, int oldLength, int newLength)
{
	if (newLength < 0)
	{
		cout << "错误:newLength 小于 0!";
		exit(-1);
	}
	T* temp = new T[newLength];
	int number = min(oldLength, newLength);
	copy(a, a + number, temp);
	delete[] a;
	a = temp;
}
//一个线性表的抽象类
template<class T>
class linearList
{
public:
	virtual ~linearList() {};
	//当线性表为空时,返回true
	virtual bool empty() const = 0;//后面加 const表示函数不可以修改class的成员,其实就是对this指针进行了const
	//返回线性表元素的个数
	virtual int size() const = 0;
	//返回索引为theIndex的元素
	virtual T& get(int theIndex) const = 0;
	//删除索引为theIndex的元素
	virtual void erase(int theIndex) = 0;
	//把theElement插入线性表中索引为theIndex的位置上
	virtual void insert(int theIndex, const T& theElement) = 0;
};

template<class T>
class arrayList:public linearList<T>
{
public:
	arrayList(int initialCapacity = 10);
	arrayList(const arrayList<T>& theList);
	~arrayList() { delete[] element; }

	bool empty() const { return listSize == 0; }
	int size() const { return listSize; }
	T& get(int theIndex) const;
	int indexOf(const T& theElement) const;
	void erase(int theIndex);
	void insert(int theIndex, const T& theElement);
	int capacity() const { return arrayLength; }
	void output(ostream& out) const;

protected:
	void checkIndex(int theIndex) const;
	friend ostream& operator<<(ostream& out, const arrayList<T>& x);
	int arrayLength;
	int listSize;
	T* element;
};
template<class T>
arrayList<T>::arrayList(int initialCapacity = 10)
{
	arrayLength = initialCapacity;
	element = new T[arrayLength];
	listSize = 0;
}

template<class T>
arrayList<T>::arrayList(const arrayList<T>& theList)
{
	arrayLength = theList.arrayLength;
	listSize = theList.listSize;
	element = new T[arrayLength];
	copy(theList.element, theList.element + listSize, element);
}

template<class T>
void arrayList<T>::checkIndex(int theIndex) const
{
	if (theIndex < 0 || theIndex >= listSize)
	{
		cout << "错误:theIndex 不合法!";
		exit(-1);
	}
}

template<class T>
T& arrayList<T>::get(int theIndex) const
{
	checkIndex(theIndex);
	return element[theIndex];
}

template<class T>
int arrayList<T>::indexOf(const T& theElement) const
{
	int theIndex = (int)(find(element, element + listSize, theElement) - element);
	if (theIndex == listSize)
		return -1;
	else
		return theIndex;
}
template<class T>
void arrayList<T>::erase(int theIndex)
{
	checkIndex(theIndex);
	copy(element + theIndex + 1, element + listSize, element + theIndex);
	//下标是从0开始的,把最后一个位置析构掉
	element[--listSize].~T();
}

template<class T>
void arrayList<T>::insert(int theIndex, const T& theElement)
{
	if (theIndex <0 || theIndex > listSize)
	{
		cout << "元素插入的theIndex下标不合理! ";
		exit(-1);
	}
	//有效索引,确定数组是否已满
	if (listSize == arrayLength)
	{
		changeLength1D(element, arrayLength, 2 * arrayLength);
		arrayLength *= 2;
	}
	//把元素向右移动一个位置
	copy_backward(element + theIndex, element + listSize, element + listSize + 1);
	element[theIndex] = theElement;
	listSize++;
}

template<typename T> ostream& operator<<(ostream& out, const arrayList<T>& x)
{
	x.output(out);
	return out;
}

template<typename T> void arrayList<T>::output(ostream& out) const
{
	//把线性表插入输出流
	copy(element, element + listSize, ostream_iterator<T>(cout, " "));
}
int main()
{
	arrayList<int> a(8);
	//测试insert函数
	a.insert(0, 5);
	a.insert(1, 4);
	a.insert(2, 3);
	a.insert(3, 2);
	a.insert(0, 1);

	//测试output函数 
	cout << "初始线性表为:";
	a.output(cout);
	cout << endl;
	cout << "初始线性表的大小为:" << a.size() << endl;

	//测试erase函数
	cout << "删除theIndex = 2的元素后线性表为:";
	a.erase(2);
	a.output(cout);
	cout << "线性表的大小为: " << a.size() << endl;

	//测试indexOf函数
	cout << "元素值为5的下标是:" << a.indexOf(5) << endl;

	//测试get函数
	cout << "下标为1的元素是:" << a.get(1) << endl;
	system("pause");
	return 0;
}

链表描述线性表

#pragma warning(disable:4996)
#include <iostream>
#include<iterator>
#include<algorithm>
using namespace std;

//一个线性表的抽象类
template<class T>
class linearList
{
public:
	virtual ~linearList() {};
	//当线性表为空时,返回true
	virtual bool empty() const = 0;//后面加 const表示函数不可以修改class的成员,其实就是对this指针进行了const
								   //返回线性表元素的个数
	virtual int size() const = 0;
	//返回索引为theIndex的元素
	virtual T& get(int theIndex) const = 0;
	//删除索引为theIndex的元素
	virtual void erase(int theIndex) = 0;
	//把theElement插入线性表中索引为theIndex的位置上
	virtual void insert(int theIndex, const T& theElement) = 0;
};

//链表节点的结构定义
template<class T>
struct chainNode
{
	T element;
	chainNode<T> *next;

	chainNode() {}
	chainNode(const T& element)
	{this->element = element;}
	chainNode(const T& element, chainNode<T>* next)
	{
		this->element = element;
		this->next = next;
	}
};

//链表
template<class T>
class chain :public linearList<T>
{
public:
	chain(int initialCapacity = 10);
	chain(const chain<T>&);
	~chain();

	bool empty() const { return listSize == 0; }
	int size() const { return listSize; }
	T& get(int theIndex) const;
	int indexOf(const T& theElement) const;
	void erase(int theIndex);
	void insert(int theIndex, const T& theElement);
	void output(ostream& out) const;

protected:
	friend ostream& operator<<(ostream& out, const chain<T>& x);
	//指向链表第一个节点的指针
	chainNode<T>* firstNode;
	//线性表的元素个数
	int listSize;
};

template<class T>
chain<T>::chain(int initialCapacity)
{
	if (initialCapacity < 1)
	{
		cout << "初始化的容量个数不能小于1" << endl;
	}
	firstNode = NULL;
	listSize = 0;
}

template<class T>
chain<T>::chain(const chain<T>& theList)
{
	listSize = theList.listSize;

	if (listSize == 0)
	{
		firstNode = NULL;
		listSize = 0;
	}

	//链表theList非空
	//用一个指针指向theList的首节点
	chainNode<T>* sourceNode = theList.firstNode;
	//赋值链表theList的首元素
	firstNode = new chainNode<T>(sourceNode->element);
	sourceNode = sourceNode->next;
	chainNode<T>* targetNode = firstNode;
	while (targetNode != NULL)
	{
		targetNode->next = new chainNode<T>(sourceNode->element);
		targetNode = targetNode->next;
		sourceNode = sourceNode->next;
	}
	sourceNode->next = NULL;
}

template<class T>
chain<T>::~chain()
{
	while (firstNode != NULL)
	{
		chainNode<T>* nextNode = firstNode->next;
		delete firstNode;
		firstNode = nextNode;
	}
}

template<class T>
T& chain<T>::get(int theIndex) const
{
	if (theIndex<0 || theIndex>listSize)
	{
		cout << "输入合法的theIndex" << endl;
		exit(-1);
	}
	chainNode<T>* currentNode = firstNode;
	for (int i = 0; i < theIndex; i++)
		currentNode = currentNode->next;
	return currentNode->element;
}

template<class T>
int chain<T>::indexOf(const T& theElement) const
{
	chainNode<T>* currentNode = firstNode;
	int index = 0;
	while (currentNode->element != theElement)
	{
		currentNode = currentNode->next;
		index++;
	}
	if (currentNode == NULL)
		return -1;
	else
		return index;
}

/*
erase需要考虑三种情况:
1.索引无效
2.删除非空表的第0个元素节点
3.删除其它元素节点
*/
template<class T>
void chain<T>::erase(int theIndex)
{
	//索引无效
	if (theIndex<0 || theIndex>listSize)
	{
		cout << "输入合法的theIndex" << endl;
		exit(-1);
	}

	chainNode<T>* deleteNode;
	if (theIndex == 0)
	{
		deleteNode = firstNode;
		firstNode = firstNode->next;
	}
	else
	{
		chainNode<T>* p = firstNode;
		//要删除某个节点需要找其前一个节点,也就是p
		for (int i = 0; i < theIndex-1; ++i)
			p = p->next;
		
		deleteNode = p->next;
		p->next = p->next->next;
	}
	listSize--;
	delete deleteNode;
}

//插入和删除一样,也得讨论三种情况
template<class T>
void chain<T>::insert(int theIndex, const T& theElement)
{
	//索引无效
	if (theIndex<0 || theIndex>listSize)
	{
		cout << "输入合法的theIndex" << endl;
		exit(-1);
	}
	
	if (theIndex == 0)
		firstNode = new chainNode<T>(theElement, firstNode);
	else
	{
		chainNode<T>* p = firstNode;
		for (int i = 0; i < theIndex - 1; ++i)
			p = p->next;

		//新创建一个节点,值为theElement,这个新节点的next为p->next
		p->next= new chainNode<T>(theElement, p->next);
	}
	listSize++;
}

//输出链表
template<class T>
void chain<T>::output(ostream& out) const
{
	for (chainNode<T>* currentNode = firstNode; currentNode != NULL;
	currentNode = currentNode->next)
		out << currentNode->element << " ";
}
template<class T>
ostream& operator<<(ostream& out, const chain<T>& x)
{
	x.output(out);
	return out;
}
int main()
{
	chain<int> c;
	//测试insert函数
	c.insert(0, 5);
	c.insert(1, 4);
	c.insert(2, 3);
	c.insert(3, 2);
	c.insert(0, 1);

	//测试output函数 
	cout << "初始线性表为:";
	c.output(cout);
	cout << endl;
	cout << "初始线性表的大小为:" << c.size() << endl;

	//测试erase函数
	cout << "删除theIndex = 2的元素后线性表为:";
	c.erase(2);
	c.output(cout);
	cout << "线性表的大小为: " << c.size() << endl;

	//测试indexOf函数
	cout << "元素值为5的下标是:" << c.indexOf(5) << endl;

	//测试get函数
	cout << "下标为1的元素是:" << c.get(1) << endl;
	
	system("pause");
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 线性表的公式化描述线性表是有限个数据元素的有顺序的集合,其元素具有相同类型,并可通过一个唯一标识符索引。 链表描述链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接构成的。每个数据元素(结点)存储数据本身以及指向下一个数据元素的指针,最后一个数据元素的指针为NULL,表示链表的结束。 ### 回答2: 线性表是一种数据结构,通常用于存储具有相同数据类型的有序元素。线性表可以通过公式化描述链表描述来实现。 公式化描述是指使用数组来实现线性表。通过定义一个固定大小的数组,元素按照一定的顺序依次存储在数组中。线性表的长度可以根据数组的大小进行控制。通过下标来访问和操作线性表中的元素,可以实现对元素的插入、删除、修改等操作。公式化描述的优点是访问元素的时间复杂度为O(1),缺点是插入和删除元素时需要移动其他元素,时间复杂度为O(n)。 链表描述是指使用指针来实现线性表链表由一系列的节点组成,每个节点包含元素的值和指向下一个节点的指针。链表的头指针指向第一个节点,尾指针指向最后一个节点。通过修改指针的指向,可以实现节点的插入、删除、修改等操作。链表描述的优点是插入和删除元素时只需改变指针的指向,时间复杂度为O(1),缺点是访问元素时需要遍历整个链表,时间复杂度为O(n)。 总结来说,公式化描述适用于对数据的访问频繁,而插入和删除操作较少的场景;链表描述适用于插入和删除操作频繁,而对数据的访问较少的场景。不同的场景可以选择不同的描述方式来实现线性表,以提高操作效率。 ### 回答3: 线性表是指具有相同数据类型的n个元素按照一定的顺序排列的数据集合。线性表可以通过两种方式进行描述,即公式化描述链表描述。 公式化描述是指使用数学公式来定义线性表的特性。一般使用一个包含n个元素的有序序列来表示线性表,每个元素在序列中的位置称为下标,从1到n,通过下标可以唯一确定每个元素的位置。线性表的公式表示为:L=(a1, a2, ..., an),其中L表示线性表的名称,a1到an表示线性表的元素。 链表描述是指利用一系列的节点来表示线性表的特性。每个节点由两部分组成,数据部分和指针部分。数据部分存储着线性表的元素,而指针部分存储着指向下一个节点的地址。链表中的节点可以随意插入或删除,使得线性表的长度可以动态地变化。链表的头节点不存储数据,仅用来指向第一个节点。链表的尾节点的指针部分为空。 在链表描述中,可以将线性表分为单链表、双链表和循环链表。单链表每个节点只有一个指针域,指向下一个节点;双链表节点除了有一个指向下一个节点的指针域,还有一个指向前一个节点的指针域;循环链表的尾节点指针部分指向头节点,形成一个循环。 通过公式化描述链表描述,我们可以方便地理解和操作线性表的结构和特性。公式化描述更适合静态的线性表,而链表描述则更适用于动态的线性表

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值