数据结构与算法设计(C++实现)实验一:线性表

本文介绍了一系列数据结构实验的设计与实现,包括顺序表与单链表的基本操作,如删除、插入、统计等,以及有序表的特殊操作,如合并、区间删除等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1.实验题目

2.实验要求

3.具体思路与代码实现

1(1)

1(2)

1(3)

2(1)

2(2)

2(3)

2(4)

3(1)

3(2)

4(1)

4(2)

附录1:测试程序(cpp文件)

第一题

第二题

第三题

第四题

附录2:顺序表类模板与单链表类模板

顺序表类模板

单链表类模板


1.实验题目

1.对存放整数的顺序表,设计函数实现以下操作:

 (1)从顺序表中删除具有最小值的元素(假设顺序表中元素都不相同),并由函数返回被删元素的值,空出的位置由最后一个元素填补。

 (2)从顺序表中删除具有给定值e的所有元素。

 (3)在一个顺序表中如果一个数据值有重复出现,则留下第一个这样的数据值,并删除其他所有重复的元素,使表中所有元素的值均不相同。

2.已知一个有序顺序表类,即表中的数据元素按数据元素值递增有序。实现以下函数:

 (1)把给定值e插入有序表中,使得插入后的表仍然有序。

 (2)删除值为e的所有数据元素。

 (3)合并两个有序表,得到一个新的有序表。

 (4)从有序顺序表中删除其值在给定值s与t之间(s<t)的所有元素,即删除取值在[s,t]之间的所有元素;如果s≥t或顺序表为空,则显示出错信息,并退出运行。

3.针对带头结点的单链表,试编写下列函数:

 (1)定位函数:在单链表中寻找第i个结点。若找到,则返回第i个结点的地址,否则返回空指针。

 (2)统计函数:统计单链表中等于给定值e的元素个数。

4.已知一个带头结点的有序单链表类,其中存放的数据元素是递增有序的。实现以下函数:

 (1)插入函数:把元素值e作为数据元素插入表中,使得插入后的表仍然有序。

 (2)删除函数:删除数据元素等于e的结点。

2.实验要求

1.函数都定义为类外普通函数,即设计一定的算法,通过调用顺序表类提供的成员函数来实现。只有第三题的第一小问需要定义为单链表类的成员函数。

2.对于第二题和第四题,不设计新类,直接用上课讲的顺序表类,假设定义的对象中数据是有序递增的。

3.具体思路与代码实现

1(1)

本题要求从顺序表中删除最小值,并以最后一个元素来填补该最小值的位置。为了达成这一 目标,首先需要通过比较找到最小值,然后用最后一个元素覆盖它。在寻找最小值时,使用 两个变量分别记录最小值及其所在位置,初始化为顺序表中的第一个元素及位置,然后从顺 序表的第 2 个元素开始依次与该最小值比较,记录更小者,从而找到顺序表的最小值和位置。 在用最后一个元素覆盖最小值时,需要注意两点:①若该最小值本身就是最后一个元素,则 只需直接将之删除即可,无需进行覆盖;②在用最后一个元素覆盖最小值后,相当于将该元 素移动到了最小值位置,此时需要将位于原本最后一个位置上的元素删除,以免重复存储。

代码实现:

template <class ElemType>
ElemType DelMinElem(SeqList<ElemType> &list)
{
    ElemType min,tmp;//min记录当前比较得到的最小值,tmp作为临时变量
    int pos;//记录最小值在线性表中的序号
    //寻找最小值min,并记录其序号pos
    list.GetElem(1,min);//取得第1个数据元素,假设为最小
    pos = 1;//当前最小值的位置,即第1个
    for(int i=2; i<=list.GetLength(); i++)//从第2个数据开始将之与min比较
    {
        list.GetElem(i,tmp);//取得第i个数据存放入tmp
        if(tmp < min)//若第i个数据比最小值小,则记录新的最小值及其位置
        {
            min = tmp;
            pos = i;
        }
    }
    //用最后一个元素替换该最小值,并删除最后一个元素
    //若最小值为最后一个元素,则无需替换
    if(pos != list.GetLength())//最小值不是最后一个元素
    {
        list.GetElem(list.GetLength(),tmp);//取得最后一个元素的值
        list.SetElem(pos,tmp);//将最小值用最后一个元素替换
    }
    list.DeleteElem(list.GetLength(),tmp);//删除最后一个元素
    return min;//返回最小值
}

1(2)

本题要求从顺序表中删除具有给定值 e 的所有元素,为达成这一目的,需要从第一个元素开 始遍历顺序表,若查找到与给定值 e 相等的元素,则将其删除,然后继续接着往后遍历,如 此反复查找删除,就能删除所有与 e 相等的元素。需要注意的是删除一个元素之后后续元素 会陆续往前移动一格,而循环计数变量 i 完成一次循环之后会自增 1,这就相当于跳过了一 个值导致其未被遍历到,所以就需要在删除一个元素的同时,对 i 进行减 1 的操作,这样就 抵消了,就不会略过被删除元素的下一个元素了。

代码实现:

template <class ElemType>
void DelValue(SeqList<ElemType>& list, const ElemType& e)
{
	ElemType tmp0;//tmp作为临时变量
	for (int i = 1; i <= list.GetLength(); i++)//从第一个元素开始遍历顺序表
	{
		list.GetElem(i, tmp0);//取得第i个数据存放入tmp0
		if (e == tmp0)//如果查找到与给定值e相等的元素,则将其删除,后续元素陆续前移一格
		{
			list.DeleteElem(i, tmp0);//删除
			--i;//回退一格,否则遍历将会跳过一格元素
		}
	}
}

1(3)

本题要求在一个顺序表中如果一个数据值有重复出现,则留下第一个这样的数据值,并删除 其他所有重复的元素,使表中所有元素的值均不相同。为达成这一目的,需要设置两个循环, 一个外循环套着一个内循环,外循环从第一个元素进行遍历,而内循环则从外循环所选择元 素的下一个元素进行遍历,若在内循环中遇到与外循环所选择元素相同的元素,则将其删除, 直至内循环遍历完成一趟结束,此时一个重复元素已被删除至只留下第一个(即外循环所选 择的那个),如此重复遍历即可删除所有重复元素并只保留第一个。需要注意的是内循环会 发生与第二小题同样的略过元素的问题,所以需要在每次删除元素之后对 j 进行减 1 的操作。

代码实现:

template <class ElemType>
void DelRepElem(SeqList<ElemType>& list)
{
	ElemType tmpi,tmpj;//内外循环各设置一个临时变量tmp
	for (int i = 1; i <= list.GetLength(); i++)
	{
		list.GetElem(i,tmpi);//取得第i个数据存放入tmpi
		for (int j = i + 1; j <= list.GetLength(); j++)
		{
			list.GetElem(j, tmpj);//取得第i个数据存放入tmpj
			if (tmpi==tmpj) //找到重复元素后删去后续的重复元素(留下第一个这样的元素)
			{
				list.DeleteElem(j, tmpj);
				j--;
			}
		}
	}
}

2(1)

本题要求把给定值 e 插入有序表中,使得插入后的表仍然有序。这题不仅要求把元素插入还 要求插入元素后不影响顺序表的有序递增性,所以需要分类讨论,即可分为插入元素值小于 有序表中的所有元素、插入元素值大小介于有序表的中间位置以及插入元素值大于有序表中 所有的元素,这样一来插入的方式便可以分为三种:①头插入 ②尾插入 ③中间插入。为此 需要创建两个临时变量用以存储原有序表的最大值和最小值,即第一个和最后一个元素,然 后依据这两个元素值划分出三个取值区间,再配合 if 判断语句即可达成分类插入的方式。 头插入和尾插入的情况很简单,只需要判断成功之后直接插入第一个和最后一个的位置即可, 中间插入的情况则需要继续细分判断:从头开始遍历有序表,每次取两个相邻的元素,用两 个临时变量储存他们,必须要满足待插入元素大于等于前一个元素且小于等于后一个元素的 条件才能将元素插入此位置。需要注意两点:①尾插入的情况下,元素插入位置并不是 length, 而应该是 length+1,即最后一个元素的后一个位置 ②中间插入的时候有遍历顺序表的操作, 需要每次同时取两个相邻的元素与要插入的元素进行对比,那么最后一对相邻的元素应该是 length-1 位置的元素和 length 位置的元素,此时计数器 i 的最大值就不能是 length,而应该 是 length-1。

代码实现:

template <class ElemType>
void OrdListInsertElem(SeqList<ElemType>& list, const ElemType& e)//分为三种情况:头插入(小于所有元素)、中间插入(介于中间)、尾插入(大于所有元素)
{
	ElemType tmpsml, tmpbig;//定义两个存储元素的临时变量用于存储头插入和尾插入两种情况下的元素
	ElemType tmpbef, tmpaft;//定义两个存储元素的临时变量用于存储合适位置的前后两个元素
	//①头插入
	list.GetElem(1, tmpsml);//获取原有序表第一个元素
	list.GetElem(list.GetLength(), tmpbig);//获取原有序表最后一个元素
	if (e <= tmpsml)//若小于所有元素则将其头插入
	{
		list.InsertElem(1, e);
	}
	//②尾插入
	else if (e >= tmpbig)//若大于所有元素则将其尾插入
	{
		list.InsertElem(list.GetLength()+1, e);
	}
	//③中间插入
	else if (tmpsml < e&& e < tmpbig)
	{
		for (int i = 1; i <= list.GetLength()-1; i++)//开始从头遍历有序顺序表,若找到大于前一个元素并小于后一个元素的位置则将其插入
		{
			list.GetElem(i, tmpbef);//获取前一个元素存入tmpbef
			list.GetElem(i + 1, tmpaft);//获取后一个元素存入tmpaft
			if (tmpbef <= e && e <= tmpaft)
			{
				list.InsertElem(i + 1, e);
				break;//若成功插入后则退出循环
			}
		}
	}
}

2(2)

本题要求删除值为 e 的所有数据元素,由于从一个递增数列中删除若干数并不影响此递增数 列的递增性,所以可以从第一个元素开始遍历查找,若查找到值为 e 的数据元素,则直接将 其删除即可。如此反复查找删除,就能删除所有与 e 相等的元素。需要注意的是删除一个元 素之后后续元素会陆续往前移动一格,而循环计数变量 i 完成一次循环之后会自增 1,这就 相当于跳过了一个值导致其未被遍历到,所以就需要在删除一个元素的同时,对 i 进行减 1 的操作,这样就抵消了,就不会略过被删除元素的下一个元素了。

代码实现:

template<class ElemType>
void OrdListDeleteElem(SeqList<ElemType>& list, const ElemType& e)
{
	ElemType tmp;//tmp作为临时变量
	for (int i = 1; i <= list.GetLength(); i++)//从第一个元素开始遍历顺序表
	{
		list.GetElem(i, tmp);//取得第i个数据存放入tmp0
		if (e == tmp)//如果查找到与给定值e相等的元素,则将其删除,后续元素陆续前移一格
		{
			list.DeleteElem(i, tmp);//删除
			--i;//回退一格,否则遍历将会跳过一格元素
		}
	}
}

2(3)

本题要求合并两个有序表,得到一个新的有序表。这题可以使用比较法的思想进行算法设计。 首先应该将两个有序表各自从头开始遍历,从两个表中同时各自取出一个元素进行比较,较 小的那个则直接使用尾插法存入新表中,然后较大的那个保留下来继续与另一个表的下一个 元素进行比较,再取较小的那个尾插存入新表中,以此类推,直至其中一个有序表的所有元 素皆已存入新表当中,最后看哪个表还有剩余,然后将那个有剩余元素的有序表的剩下的部 分全部直接尾插到新表后面。这样一来就实现了两个有序表的合并操作

代码实现:

template<class ElemType>
Status OrdListMerge(const SeqList<ElemType>& lista, const SeqList<ElemType>& listb, SeqList<ElemType>& listc)
{
	if (lista.GetLength() + listb.GetLength() > 50) return RANGE_ERROR;//如果原来的两个有序表的长度加起来大于新有序表的容量,那么退出程序并报告长度错误
	else//如果长度在新有序表的范围内,则进行合并操作
	{
		int i = 1, j = 1;//为两个原有序表分别设置一个计数器
		ElemType tmpa, tmpb;//存储两个原有序表各自元素的两个临时变量
		//两个有序表各自从头开始按照顺序不断将两个有序表中对应的元素进行比较,较小的那个元素存入新表中,然后较大的那个元素保留下来继续与另一个有序表的下一个元素进行比较,以此类推,直至操作结束后,看哪个表还有剩余,这些剩余必定是较大的元素,直接将这些剩下的部分加到新表后面即可。
		while (i <= lista.GetLength() && j <= listb.GetLength())//当有序表a和有序表b的的长度作为循环条件,只要有一个表的元素都被存入新表了,那么循环结束
		{
			lista.GetElem(i, tmpa);//取得有序表a的第i个数据存放入tmpa
			listb.GetElem(j, tmpb);//取得有序表b的第j个数据存放入tmpb
			if (tmpa <= tmpb)//如果tmpa小于等于tmpb,则将tmpa使用尾插法存入新表中
			{
				listc.InsertElem(tmpa);//将有序表a的第i个元素用尾插法存入新表
				i++;//有序表a的计数器加一
			}
			else//如果tmpa大于tmpb,则将tmpb使用尾插法存入新表中
			{
				listc.InsertElem(tmpb);//将有序表b的第j个元素用尾插法存入新表
				j++;//有序表b的计数器加一
			}
		}
		//比较操作结束后,看哪个表还有剩余,直接将这些剩下的部分加到新表后面即可
		while (i <= lista.GetLength())//若有序表a有剩余,则使用while循环将它们一一存入新表
		{
			lista.GetElem(i, tmpa);//取得有序表a的第i个数据存放入tmpa
			listc.InsertElem(tmpa);//尾插法插入
			i++;//计数器加一
		}
		while (j <= listb.GetLength())//若有序表a有剩余,则使用while循环将它们一一存入新表
		{
			listb.GetElem(i, tmpb);//取得有序表b的第j个数据存放入tmpb
			listc.InsertElem(tmpb);//尾插法插入
			j++;//计数器加一
		}
		return SUCCESS;//两个有序表合并成一个新表后,返回成功信息
	}
}

2(4)

本题要求从有序顺序表中删除其值在给定值 s 与 t 之间(s<t)的所有元素,即删除取值在 [s,t]之间的所有元素;如果 s≥t 或顺序表为空,则显示出错信息,并退出运行。本题目的思 路与本大题的第二小题非常相似,都是从第一个元素开始遍历顺序表,但是第二小题是“若 查找到值为 e 的数据元素,则直接将其删除”,而本题可以将这个确切的值 e 替换为一个闭 区间范围[s,t],所以判断条件应该从“e = = tmp”变成“tmp >= s && tmp <= t”。这样一来就 实现了范围性删除的操作。这题也要注意每次删除元素之后计数器要减 1 以抵消 i 的自增。

代码实现:

template<class ElemType>
Status OrdListIntervalDelete(SeqList<ElemType>& list, const ElemType& s, const ElemType& t)
{
	if (s >= t || list.GetLength() == 0) return RANGE_ERROR;//如果s≥t或顺序表为空,则显示出错信息,并退出运行
	else
	{
		ElemType tmp;//tmp作为临时变量
		for (int i = 1; i <= list.GetLength(); i++)//从第一个元素开始遍历顺序表
		{
			list.GetElem(i, tmp);//取得第i个数据存放入tmp
			if ( tmp>=s && tmp<=t)//如果查找到在[s,t]之间的元素,则将其删除,后续元素陆续前移一格
			{
				list.DeleteElem(i, tmp);//删除
				--i;//回退一格,否则遍历将会跳过一格元素
			}
		}
		return SUCCESS;
	}
}

3(1)

本题要求在类内设计一个定位函数,用于在单链表中寻找第 i 个结点。若找到,则返回第 i 个结点的地址,否则返回空指针。首先应该先判断 i 的值。若 i 的值比 1 小或者比链表的长 度 length 还大,则直接退出并返回空指针。若 i 的值在 1 到 length 的范围内,则定义一个 指针,先将指针定位到头结点的 next,后将指针不断指向该结点的 next 结点进行遍历,重 复 i 次,找到第 i 个结点后便将该结点地址返回。

代码实现:

Node<ElemType>* LocateAddress(int i)
	{
		if (i<1 || i>length)//若结点不在 1 到 length 的范围内,即不存在此结点,则返回空指
针

        {
			return NULL;//返回空指针
		}
		else 
		{
			Node<ElemType>* p = head->next;//定义一个指向头结点的 next 的指针
			for (int count = 1; count < i; count++)//进行循环,直至找到第 i 个结点

			{
				p = p->next;//将指针不断指向该结点的 next 结点
			}
			return p;//返回所找到的结点的地址
		}
	}
};

3(2)

本题要求设计一个统计函数,用于统计单链表中等于给定值 e 的所有元素个数,这显然需要 一个变量来计数,为此需要创建一个 int 类型的变量 freq 进行计数操作。然后对单链表从第 一个元素开始进行遍历,若遇到与给定值 e 相等的数据,则对计数器 freq 进行加 1,遍历完 成之后返回的 freq 值就是统计结果。

代码实现:

template <class ElemType>
int Frequency(const LinkList<ElemType>& la, const ElemType& e)
{
	int freq = 0;//计数的临时变量
	ElemType tmp;//储存数据的临时变量
	for (int i = 0; i < la.GetLength(); i++)
	{
		la.GetElem(i, tmp); //取得第i个数据存放入tmp
		if (e == tmp)
			freq++;//如果有等于的就加一
	}
	return freq;
}

4(1)

由于实验要求将所写的函数都必须要定义为类外普通函数,即设计一定的算法,通过调用单 链表类提供的成员函数来实现。所以本题与实验第二题的第一小问的思路大致相同,即可分 为插入元素值小于有序链表中的所有元素、插入元素值大小介于有序链表的中间位置以及插 入元素值大于有序链表中所有的元素,这样一来插入的方式便可以分为三种:①头插入 ② 尾插入 ③中间插入。为此需要创建两个临时变量用以存储原有序链表的最大值和最小值, 即第一个和最后一个元素,然后依据这两个元素值划分出三个取值区间,再配合 if 判断语 句即可达成分类插入的方式。头插入和尾插入的情况很简单,只需要判断成功之后直接插入 第一个和最后一个的位置即可,中间插入的情况则需要继续细分判断:从头开始遍历有序链 表,每次取两个相邻的元素,用两个临时变量储存他们,必须要满足待插入元素大于等于前 一个元素且小于等于后一个元素的条件才能将元素插入此位置。需要注意两点:①尾插入的 情况下,元素插入位置并不是 length,而应该是 length+1,即最后一个元素的后一个位置 ② 中间插入的时候有遍历顺序表的操作,需要每次同时取两个相邻的元素与要插入的元素进行 对比,那么最后一对相邻的元素应该是 length-1 位置的元素和 length 位置的元素,此时计数 器 i 的最大值就不能是 length,而应该是 length-1。

代码实现:

template <class ElemType>
void OrdListInsertElem(LinkList<ElemType>& la, const ElemType& e)//分为三种情况:头插入(小于所有元素)、中间插入(介于中间)、尾插入(大于所有元素)
{
	ElemType tmpsml, tmpbig;//定义两个存储元素的临时变量用于存储头插入和尾插入两种情况下的元素
	ElemType tmpbef, tmpaft;//定义两个存储元素的临时变量用于存储合适位置的前后两个元素
	//①头插入
	la.GetElem(1, tmpsml);//获取链表第一个元素
	la.GetElem(la.GetLength(), tmpbig);//获取链表最后一个元素
	if (e <= tmpsml)//若小于原链表所有元素则将其头插入
	{
		la.InsertElem(1, e);
	}
	//②尾插入
	else if (e >= tmpbig)//若大于原链表所有元素则将其尾插入
	{
		la.InsertElem(la.GetLength() + 1, e);
	}
	//③中间插入
	else if (tmpsml < e && e < tmpbig)
	{
		for (int i = 1; i <= la.GetLength() - 1; i++)//开始从头遍历链表,若找到大于前一个元素并小于后一个元素的位置则将其插入
		{
			la.GetElem(i, tmpbef);//获取前一个元素存入tmpbef
			la.GetElem(i + 1, tmpaft);//获取后一个元素存入tmpaft
			if (tmpbef <= e && e <= tmpaft)
			{
				la.InsertElem(i + 1, e);
				break;//若成功插入后则退出循环
			}
		}
	}
}

4(2)

由于实验要求将所写的函数都必须定义为类外普通函数,即设计一定的算法,通过调用单链 表类提供的成员函数来实现。所以本题与实验第二题的第二小问的思路大致相同,即由于从 一个递增数列中删除若干数并不影响此递增数列的递增性,所以可以从第一个元素开始遍历 查找,若查找到值为 e 的数据元素,则直接将其删除即可。如此反复查找删除,就能删除所 有与 e 相等的元素。需要注意的是删除一个元素之后后续元素会陆续往前移动一格,而循环 计数变量 i 完成一次循环之后会自增 1,这就相当于跳过了一个值导致其未被遍历到,所以 就需要在删除一个元素的同时,对 i 进行减 1 的操作,这样就抵消了,就不会略过被删除元 素的下一个元素了。

代码实现:

template<class ElemType>
void OrdListDeleteElem(LinkList<ElemType>& la, const ElemType& e)
{
	ElemType tmp;//tmp作为临时变量
	for (int i = 1; i <= la.GetLength(); i++)//从第一个元素开始遍历链表
	{
		la.GetElem(i, tmp);//取得第i个数据存放入tmp
		if (e == tmp)//如果查找到与给定值e相等的元素,则将其删除,后续元素陆续前移一格
		{
			la.DeleteElem(i, tmp);//删除
			--i;//回退一格,否则遍历将会跳过一格元素
		}
	}
}

附录1:测试程序(cpp文件)

第一题

#include <iostream>
#include <assert.h>
using namespace std;
#include "SeqList.h"

//用于顺序表元素的输出
template <class ElemType>
void Display(const ElemType & e) 
{    cout << e << "  ";    }

//测试主函数
int main(void)
{
	SeqList<int> list(11);
	int num,min,dx;
	cout << "Please enter 11 integers(6 32 3 11 11 11 41 26 11 5 22):" << endl;//输入:6 32 3 11 11 11 41 26 11 5 22
	for(int i=1; i<=11; i++)
	{
		cin >> num;
		list.InsertElem(num);
	}

	//-------以下用于测试第1小题-------------------------
	min = DelMinElem(list);//------对第1小题函数的调用
	cout << "The current min value is: " << min << endl;
	cout << "After deleting the min value, the list is: " << endl;
	list.Traverse(Display);
	cout << endl;
	min = DelMinElem(list);//------对第1小题函数的调用
	cout << "The current min value is: " << min << endl;
	cout << "After deleting the min value, the list is:" << endl;
	list.Traverse(Display);
	cout << endl;
	min = DelMinElem(list);//------对第1小题函数的调用
	cout << "The current min value is: " << min << endl;
	cout << "After deleting the min value, the list is:" << endl;
	list.Traverse(Display);
	cout << endl << endl;

	//-------以下用于测试第2小题-------------------------
	cout << "Please enter an integer to be deleted(22): " << endl;//输入:22
	cin >> dx;
	if(list.LocateElem(dx))
	{
		DelValue(list,dx);//------对第2小题函数的调用
		cout << "The deleted list is:" << endl;
		list.Traverse(Display);
		cout << endl << endl;
	}
	else
		cout << "Not found!" << endl;
	cout << "Please enter an integer to be deleted(26): " << endl;//输入:26
	cin >> dx;
	if (list.LocateElem(dx))
	{
		DelValue(list, dx);//------对第2小题函数的调用
		cout << "The deleted list is:" << endl;
		list.Traverse(Display);
		cout << endl << endl;
	}
	else
		cout << "Not found!" << endl;
	cout << "Please enter an integer to be deleted(11): " << endl;//输入:11
	cin >> dx;
	if(list.LocateElem(dx))
	{
		DelValue(list,dx);//------对第2小题函数的调用
		cout << "The deleted list is:" << endl;
		list.Traverse(Display);
		cout << endl << endl;
	}
	else
		cout << "Not found!" << endl << endl;

	//--------------以下用于测试第3小题--------------------------------------------
	list.GetElem(1,num);	list.InsertElem(num);	list.InsertElem(num);
	list.GetElem(2,num);	list.InsertElem(num);
	list.GetElem(3,num);	list.InsertElem(2,num);	list.InsertElem(num);
	cout << "The current list is:" << endl;
	list.Traverse(Display);
	cout << endl;
	DelRepElem(list);//------对第3小题函数的调用
	cout << "After deleting duplicate elements, the list is:" << endl;
	list.Traverse(Display);
	cout << endl << endl;

	system("pause");
	return 0;
}

第二题

#include <iostream>
using namespace std;
#include <assert.h>
#include "SeqList.h"

//用于顺序表元素的输出
template <class ElemType>
void Display(const ElemType & e) 
{    cout << e << "  ";    }

//测试主函数
int main(void)
{
	SeqList<int> list1(50),list2(50),list3(50);
	int num,data;

	cout << "Please enter 11 ordered integers(5 10 11 22 27 33 44 44 55 56 60):" << endl;//输入:5 10 11 22 27 33 44 44 55 56 60
	for(int i=1; i<=11; i++)
	{
		cin >> num;
		list1.InsertElem(num);
	}

	//------------以下用于测试第1小题---------------------------------
	cout << "Please enter an integer to be inserted(3):" << endl;
	cin >> data;//输入:3
	OrdListInsertElem(list1,data);//----------调用第1小题函数
	cout << "After insertion, list1 is:" << endl;
	list1.Traverse(Display);
	cout << endl;
	cout << "Please enter an integer to be inserted(27):" << endl;
	cin >> data;//输入:27
	OrdListInsertElem(list1,data);//----------调用第1小题函数
	cout << "After insertion, list1 is:" << endl;
	list1.Traverse(Display);
	cout << endl;
	cout << "Please enter an integer to be inserted(77):" << endl;
	cin >> data;//输入:77
	OrdListInsertElem(list1,data);//----------调用第1小题函数
	cout << "After insertion, list1 is:" << endl;
	list1.Traverse(Display);
	cout << endl << endl;
	
	//------------以下用于测试第2小题---------------------------------
	cout << "Please enter an integer to be deleted(3):" << endl;
	cin >> data;//输入:3
	OrdListDeleteElem(list1,data);//----------调用第2小题函数
	cout << "After deletion, list1 is:" << endl;
	list1.Traverse(Display);
	cout << endl;
	cout << "Please enter an integer to be deleted(27):" << endl;
	cin >> data;//输入:27
	OrdListDeleteElem(list1,data);//----------调用第2小题函数
	cout << "After deletion, list1 is:" << endl;
	list1.Traverse(Display);
	cout << endl;
	cout << "Please enter an integer to be deleted(77):" << endl;
	cin >> data;//输入:77
	OrdListDeleteElem(list1,data);//----------调用第2小题函数
	cout << "After deletion, list1 is:" << endl;
	list1.Traverse(Display);
	cout << endl << endl;

	//------------以下用于测试第3小题---------------------------------
	cout << "Please enter 5 integers(5 27 30 36 77):" << endl;//输入:5 27 30 36 77
	for(int i=1; i<=5; i++)
	{
		cin >> num;
		list2.InsertElem(num);
	}
	if(OrdListMerge(list1,list2,list3) == SUCCESS)//---------调用第3小题函数
	{
		cout << "The merged list3 is:" << endl;
		list3.Traverse(Display);
	}
	else
		cout << "The space of list3 is insufficient!";
	cout << endl << endl;

	//------------以下用于测试第4小题---------------------------------
	int s,t;
	cout << "Please enter the lower bound of the deleted integer(0):" << endl;
	cin >> s;//输入:0
	cout << "Please enter the upper bound of the deleted integer(11):" << endl;
	cin >> t;//输入:11
	if(OrdListIntervalDelete(list3,s,t) == SUCCESS)//---------调用第4小题函数
	{
		cout << "After deletion, list3 is:" << endl;
		list3.Traverse(Display);
		cout << endl;
	}
	cout << "Please enter the lower bound of the deleted integer(30):" << endl;
	cin >> s;//输入:30
	cout << "Please enter the upper bound of the deleted integer(50):" << endl;
	cin >> t;//输入:50
	if(OrdListIntervalDelete(list3,s,t) == SUCCESS)//---------调用第4小题函数
	{
		cout << "After deletion, list3 is:" << endl;
		list3.Traverse(Display);
		cout << endl;
	}
	cout << "Please enter the lower bound of the deleted integer(58):" << endl;
	cin >> s;//输入:58
	cout << "Please enter the upper bound of the deleted integer(100):" << endl;
	cin >> t;//输入:100
	if(OrdListIntervalDelete(list3,s,t) == SUCCESS)//---------调用第4小题函数
	{
		cout << "After deletion, list3 is:" << endl;
		list3.Traverse(Display);
		cout << endl;
	}
	cout << endl;

	system("pause");
	return 0;
}

第三题

#include <iostream>
#include <assert.h>
using namespace std;
#include "Node.h"
#include "LinkList.h"

template <class ElemType>
void Display(const ElemType & e) 
{    cout << e << "    ";    }


int main(void)
{
	LinkList<int> list;
	Node<int> *p;
	int data;

	cout << "Please enter 10 integers(21 32 3 11 11 11 41 26 11 5):" << endl;//输入:21 32 3 11 11 11 41 26 11 5
	for(int i=1; i<=10; i++)
	{
		cin >> data;
		list.InsertElem(data);
	}
	
	//-------以下用于测试第1小题-------------------------
	cout << "Please enter the serial number of the data to be located(1):" << endl;
	cin >> data;//输入:1
	if(p=list.LocateAddress(data))//-------------对第1小题成员函数的调用
		cout << "The address of the data is: " << p << endl;
	else
		cout << "The serial number is wrong!" << endl;
	cout << "Please enter the serial number of the data to be located(5):" << endl;
	cin >> data;//输入:5
	if(p=list.LocateAddress(data))//-------------对第1小题成员函数的调用
		cout << "The address of the data is: " << p << endl;
	else
		cout << "The serial number is wrong!" << endl;
	cout << "Please enter the serial number of the data to be located(15):" << endl;
	cin >> data;//输入:15
	if (p = list.LocateAddress(data))//-------------对第1小题成员函数的调用
		cout << "The address of the data is: " << p << endl;
	else
		cout << "The serial number is wrong!" << endl;
	cout << endl;

	//-------以下用于测试第2小题-------------------------
	cout << "Please enter the data to be counted(3):" << endl;
	cin >> data;//输入:3
	cout << "The number of the data to be counted is: " << Frequency(list,data) << endl;//-------------对第2小题成员函数的调用
	cout << "Please enter the data to be counted(11):" << endl;
	cin >> data;//输入:11
	cout << "The number of the data to be counted is: " << Frequency(list,data) << endl;//-------------对第2小题成员函数的调用
	cout << "Please enter the data to be counted(7):" << endl;
	cin >> data;//输入:7
	cout << "The number of the data to be counted is: " << Frequency(list, data) << endl;//-------------对第2小题成员函数的调用
	cout << endl;

	system("pause");
	return 0;
}

第四题

#include <iostream>
#include <assert.h>
using namespace std;
#include "Node.h"
#include "LinkList.h"

template <class ElemType>
void Display(const ElemType & e) 
{    cout << e << "    ";    }

int main(void)
{
	LinkList<int> list;
	int data;

	cout << "Please enter 11 ordered integers(5 10 11 22 27 33 44 44 55 56 60):" << endl;//输入:5 10 11 22 27 33 44 44 55 56 60
	for(int i=1; i<=11; i++)
	{
		cin >> data;
		list.InsertElem(data);
	}
	
	//------------以下用于测试第1小题---------------------------------
	cout << "Please enter an integer to be inserted(3):" << endl;
	cin >> data;//输入:3
	OrdListInsertElem(list,data);//----------调用第1小题函数
	cout << "After insertion, list is:" << endl;
	list.Traverse(Display);
	cout << endl;
	cout << "Please enter an integer to be inserted(27):" << endl;
	cin >> data;//输入:27
	OrdListInsertElem(list,data);//----------调用第1小题函数
	cout << "After insertion, list is:" << endl;
	list.Traverse(Display);
	cout << endl;
	cout << "Please enter an integer to be inserted(77):" << endl;
	cin >> data;//输入:77
	OrdListInsertElem(list,data);//----------调用第1小题函数
	cout << "After insertion, list is:" << endl;
	list.Traverse(Display);
	cout << endl << endl;
	
	//------------以下用于测试第2小题---------------------------------
	cout << "Please enter an integer to be deleted(3):" << endl;
	cin >> data;//输入:3
	OrdListDeleteElem(list, data);//----------调用第2小题函数
	cout << "After deletion, list is:" << endl;
	list.Traverse(Display);
	cout << endl;
	cout << "Please enter an integer to be deleted(27):" << endl;
	cin >> data;//输入:27
	OrdListDeleteElem(list,data);//----------调用第2小题函数
	cout << "After deletion, list is:" << endl;
	list.Traverse(Display);
	cout << endl;
	cout << "Please enter an integer to be deleted(77):" << endl;
	cin >> data;//输入:77
	OrdListDeleteElem(list,data);//----------调用第2小题函数
	cout << "After deletion, list is:" << endl;
	list.Traverse(Display);
	cout << endl << endl;

	system("pause");
	return 0;
}

附录2:顺序表类模板与单链表类模板

顺序表类模板

#pragma once
//SeqList.h
typedef enum { NOT_PRESENT, ENTRY_FOUND, RANGE_ERROR, SUCCESS, OVER_FLOW } Status;//定义枚举类型

template <class ElemType>//模板形参为元素数据类型
class SeqList
{
protected:
    int length;	//顺序表目前存储的元素个数			
    int maxLength;//顺序表的最大容量			
    ElemType* elems;//元素
public:
    SeqList(int size );
    SeqList(ElemType v[], int n, int size );
    virtual ~SeqList();
    int GetLength() const;
    bool IsEmpty() const;
    void Clear();
    void Traverse(void (*visit)(const ElemType&)) const;
    int LocateElem(const ElemType& e) const;
    Status GetElem(int i, ElemType& e) const;
    Status SetElem(int i, const ElemType& e);
    Status DeleteElem(int i, ElemType& e);
    Status InsertElem(int i, const ElemType& e);
    Status InsertElem(const ElemType& e);
    SeqList(const SeqList<ElemType>& sa);
    SeqList<ElemType>& operator=(const SeqList<ElemType>& sa);
};



//以下为类模板实现的部分
template <class ElemType>
SeqList<ElemType>::SeqList(int size)//构造空顺序表
{
    elems = new ElemType[size];
    assert(elems);
    maxLength = size;
    length = 0;
}

template <class ElemType>
SeqList<ElemType>::SeqList(ElemType v[], int n, int size)//根据已有数组构造顺序表 
{
    elems = new ElemType[size];
    assert(elems);
    maxLength = size;
    length = n;
    for (int i = 0; i < length; i++)
        elems[i] = v[i];
}

template <class ElemType>//析构函数
SeqList<ElemType>::~SeqList()
{
    delete[]elems;
}

template <class ElemType>//清空顺序表
void SeqList<ElemType>::Clear()
{
    length = 0;
}

template <class ElemType>//遍历顺序表
void SeqList<ElemType>::Traverse(void (*visit)(const ElemType&)) const
{
    for (int i = 1; i <= length; i++)
        (*visit)(elems[i - 1]);
}

template <class ElemType>//定位某一元素的函数
int SeqList<ElemType>::LocateElem(const ElemType& e) const
{
    int i = 0;
    while (i < length && elems[i] != e)        i++;
    return i < length ? i + 1 : 0;//存在值为e的元素则返回i+1,否则返回0
}

template <class ElemType>//取指定元素的函数
Status SeqList<ElemType>::GetElem(int i, ElemType& e) const
{
    if (i < 1 || i > length)	return NOT_PRESENT;
    else
    {
        e = elems[i - 1];
        return ENTRY_FOUND;
    }
}

template <class ElemType>
Status SeqList<ElemType>::SetElem(int i, const ElemType& e)//修改指定元素的值,i为要修改的元素序号,e为用以替换的值
{
    if (i < 1 || i > length)	return RANGE_ERROR;
    else {
        elems[i - 1] = e;
        return SUCCESS;
    }
}

template <class ElemType>//删除指定元素
Status SeqList<ElemType>::DeleteElem(int i, ElemType& e)
{
    if (i < 1 || i > length)
        return RANGE_ERROR;
    else {
        e = elems[i - 1];
        for (int j = i; j < length; j++) //移动元素
            elems[j - 1] = elems[j];
        length--;
        return SUCCESS;
    }
}

template <class ElemType>
Status SeqList<ElemType>::InsertElem(int i, const ElemType& e)//在任意位置插入元素
{
    if (length == maxLength)	return OVER_FLOW;
    else if (i < 1 || i > length + 1)   return RANGE_ERROR;
    else {
        for (int j = length; j >= i; j--)  //移动元素
            elems[j] = elems[j - 1];
        elems[i - 1] = e;
        length++;
        return SUCCESS;
    }
}

template <class ElemType>
Status SeqList<ElemType>::InsertElem(const ElemType& e)//在表尾插入元素
{
    if (length == maxLength)
        return OVER_FLOW;
    else {
        elems[length] = e;
        length++;
        return SUCCESS;
    }
}


//取顺序表的长度
template <class ElemType>
int SeqList<ElemType>::GetLength() const {
    return length;
}
//判断顺序表是否为空
template <class ElemType>
bool SeqList<ElemType>::IsEmpty() const {
    return length ? false : true;
}
//拷贝构造函数
template <class ElemType>
SeqList<ElemType>::SeqList(const SeqList<ElemType>& sa) {
    elems = new ElemType[sa.maxLength];
    assert(elems);
    maxLength = sa.maxLength;
    length = sa.length;
    for (int i = 0; i < length; i++)
        elems[i] = sa.elems[i];
}
//赋值运算符重载
template <class ElemType>
SeqList<ElemType>& SeqList<ElemType>::operator=(const SeqList<ElemType>& sa) {
    if (this == &sa)	return *this;
    if (elems)	delete[]elems;
    elems = new ElemType[sa.maxLength];
    assert(elems);
    maxLength = sa.maxLength;    length = sa.length;
    for (int i = 0; i < length; i++)    elems[i] = sa.elems[i];
    return *this;
}

单链表类模板

1.结点模板

#pragma once
//Node.h
template <class ElemType>
struct Node
{
	ElemType data;
	Node<ElemType>* next;
	Node(); //构造头结点
			//构造数据元素结点
	Node(ElemType e, Node<ElemType>* link = NULL);
};

template<class ElemType>
Node<ElemType>::Node()
{
	next = NULL;
}

template<class ElemType>
Node<ElemType>::Node(ElemType e, Node<ElemType>* link)
{
	data = e;
	next = link;
}

2.链表模板

#pragma once
//LinkList.h
#include "Node.h"
typedef enum { NOT_PRESENT, ENTRY_FOUND, RANGE_ERROR, SUCCESS, OVER_FLOW } Status;//状态参数
template <class ElemType>
class LinkList
{
protected:
	Node<ElemType>* head;
	int length;
public:
	LinkList();
	LinkList(ElemType v[], int n);
	virtual ~LinkList();
	int GetLength() const;
	bool IsEmpty() const;
	void Clear();
	void Traverse(void (*Visit)(const ElemType&)) const;
	int LocateElem(const ElemType& e) const;
	Status GetElem(int i, ElemType& e) const;
	Status SetElem(int i, const ElemType& e);
	Status DeleteElem(int i, ElemType& e);
	Status InsertElem(int i, const ElemType& e);
	Status InsertElem(const ElemType& e);
	//LinkList(const LinkList<ElemType>& la);
	LinkList<ElemType>& operator =(const LinkList<ElemType>& la);
};

template <class ElemType>
LinkList<ElemType>::LinkList()//无参构造函数
{
	head = new Node<ElemType>;
	assert(head);
	length = 0;
}

template <class ElemType>
LinkList<ElemType>::LinkList(ElemType v[], int n)//根据数组内容构造链表 
{
	Node<ElemType>* p;//辅助指针,始终指向当前链表最后一个结点
	p = head = new Node<ElemType>;
	assert(head);
	for (int i = 0; i < n; i++) {
		p->next = new Node<ElemType>(v[i], NULL);
		assert(p->next);
		p = p->next;
	}
	length = n;
}

template <class ElemType>
LinkList<ElemType>::~LinkList()//析构函数
{
	Clear();
	delete head;
}

template <class ElemType>
void LinkList<ElemType>::Clear()//清空单链表
{
	Node<ElemType>* p = head->next;
	while (p != NULL) {
		head->next = p->next;
		delete p;
		p = head->next;
	}
	length = 0;
}

template <class ElemType>
void LinkList<ElemType>::Traverse(void (*Visit)(const ElemType&)) const//遍历链表
{
	Node<ElemType>* p = head->next;
	while (p != NULL) {
		(*Visit)(p->data);
		p = p->next;
	}
}

template <class ElemType>
int LinkList<ElemType>::LocateElem(const ElemType& e) const//元素定位
{
	Node<ElemType>* p = head->next;
	int count = 1;
	while (p != NULL && p->data != e) {
		count++;
		p = p->next;
	}
	return (p != NULL) ? count : 0;
}

template <class ElemType>
Status LinkList<ElemType>::GetElem(int i, ElemType& e) const//取指定元素的值 
{
	if (i < 1 || i > length)   return RANGE_ERROR;
	else {
		Node<ElemType>* p = head->next;
		int count;
		for (count = 1; count < i; count++)
			p = p->next;
		e = p->data;
		return ENTRY_FOUND;
	}
}

template <class ElemType>
Status LinkList<ElemType>::SetElem(int i, const ElemType& e)//修改指定元素的值
{
	if (i < 1 || i > length)	  return RANGE_ERROR;
	else {
		Node<ElemType>* p = head->next;
		int count;
		for (count = 1; count < i; count++)
			p = p->next;
		p->data = e;
		return SUCCESS;
	}
}

template <class ElemType>
Status LinkList<ElemType>::DeleteElem(int i, ElemType& e)//删除指定元素
{
	if (i < 1 || i > length)   return RANGE_ERROR;
	else {
		//p指向待删结点的前驱
		Node<ElemType>* p = head, * q;
		int count;
		for (count = 1; count < i; count++)	p = p->next;
		q = p->next;	p->next = q->next; 	e = q->data;
		length--; 	delete q;	return SUCCESS;
	}
}

template <class ElemType>
Status LinkList<ElemType>::InsertElem(int i, const ElemType& e)//在任意位置插入元素
{
	if (i < 1 || i > length + 1)   return RANGE_ERROR;
	else {//p指向待插位置的前驱
		Node<ElemType>* p = head, * q;
		int count;
		for (count = 1; count < i; count++)	p = p->next;
		q = new Node<ElemType>(e, p->next);
		assert(q);
		p->next = q;	length++;      return SUCCESS;
	}
}

template <class ElemType>
Status LinkList<ElemType>::InsertElem(const ElemType& e)//在表尾插入元素
{
	Node<ElemType>* p, * q;
	q = new Node<ElemType>(e, NULL);
	assert(q);
	for (p = head; p->next != NULL; p = p->next);
	p->next = q;
	length++;
	return SUCCESS;
}

template <class ElemType>
int LinkList<ElemType>::GetLength() const //取长度
{
	return length;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值