【数据结构】顺序表的代码实现

顺序表

注意:代码主要是用C++写的,对C语言有兼容性。

写在前面的话

相信很多人在看数据结构这本书的时候都云里雾里,书中的代码让人费解,而且代码还只是冰山一角,像我这种愚蠢的家伙就很是不解,照着书上的算法描述敲代码,结果就是一片红色警告。
ElemType是什么类型?C或者C++有这种类型吗?为什么会报错。
Status又是什么东西锕,怎么和书上写的一样都会报错锕…
这里,我们不说那些定义和特点,那些书上都有。
今天,我们只看代码该如何实现。

实现代码的前提

首先,书中并没有写明main函数的具体实现,这里就由我自由发挥了。
然后,你需要了解一些关键知识。
比如:typedef 这个关键字就是为了给变量或什么东西起外号的,虽然它并不一定喜欢这个外号,也许这个外号让它的一世英名毁于一旦。但在个文件里,大家都这么叫它,都知道这个外号指的就是它。对此,它也无能为力。
语法:typedef 原名 外号;
示例:

typedef Book ElemType;

还有就是,原文中字符是直接用==比较的:L.elem[i] == e
但我们这里的数据类型是Book,外号叫ElemType
这种类型不能直接使用比较运算符,必须对运算符进行重载。
为了简化,我把图书结构中的一些字符型成员变量改成了字符串型。
最后,顺序表是从1开始的。顺序表的方法先是初始化方法,然后需要获取数据的方法,还需要能知道数据放在哪个位置的方法,还需要能增加数据的插入方法和删除数据的删除方法。

代码实现

看懂代码最关键的语句:

//给Book类型取外号为ElemType
typedef Book ElemType;
//给int类型取外号为Status
typedef int Status;

知道ElemTypeStatus都是外号后,理解起来就简单起来了。

#include<iostream>
#include<string>

using namespace std;

#define MAXSIZE 10  //宏定义,定义数组最大长度,对应顺序表的容量

//图书结构
typedef struct
{
	string no; //图书ISBN编号
	string name;  //图书名称
	float price;  //图书价格
}Book;

//顺序表结构
typedef struct
{
	Book* elem; //定义Book指针
	int length; //顺序表的长度
	int MaxSize;//此处为扩展知识,书上没有
}SqList;

//给Book类型取外号为ElemType
typedef Book ElemType;
//给int类型取外号为Status
typedef int Status;


/*
	顺序表的初始化:
	参数一:要初始化的顺序表
	注意:成功:返回1;失败:退出程序,错误代码:3。
*/
Status InitList(SqList& L)//使用int类型的外号Status作为函数的返回值类型
{
	L.MaxSize = MAXSIZE;
	//L.elem = (Book*)malloc(MAXSIZE*sizeof(int)); //或者用malloc开辟空间
	L.elem = new ElemType[MAXSIZE]; //使用Book类型的外号ElemType
	//exit是退出整个进程,OVERFLOW的默认值为3,意思为栈溢出
	if (!L.elem) exit(OVERFLOW);
	L.length = 0;
	return 1;
}

/*
	顺序表的扩容(扩展知识,书上并没有这个)
	扩容会大量移动数据,时间复杂度为O(n)
*/
void IncreaseSize(SqList &L,int len)
{
	Book *p = L.elem;//将原来的地址给p
	L.MaxSize += len;//容量加上扩容的数据
	
	L.elem = new Book[L.MaxSize];//开辟新空间
	//L.elem = (Book*)malloc(L.MaxSize*sizeof(int));
	for (int i = 0; i < L.length; i++)//将原来的数据拷贝回来
	{
		/*
			此处编译器警告:代码:C6385 说明:正在从"L.elem"读取无效数据。
			尚不清楚是怎么回事,然而并不影响程序运行。
		*/
		L.elem[i] = p[i];
	}

	//delete(p);//这里应当释放的,但是这样编译器报错,程序崩溃。
	//free(p);//如果用malloc开辟空间,就用free释放
}

/*
	顺序表的取值:时间复杂度为O(1)
	参数一:要取值的顺序表
	参数二:要取值的位置
	参数三:待保存的对象
	注意:成功:返回1;失败:返回0。
*/
Status GetElem(SqList& L, int num, ElemType& e)//使用Book类型的外号ElemType作为传入参数e的类型,使用int类型的外号Status作为函数的返回值类型
{
	if (num<1 || num>L.length)//先判断输入是否合法
	{
		return 0;
	}
	e = L.elem[num - 1]; //将获取的数值赋值给Book对象e
	return 1;
}

/*
	顺序表的查找:时间复杂度为O(n)
	参数一:要查找的顺序表
	参数二:要查找的数据
	注意:成功:返回下标位置;失败:返回0。
*/
Status LocateElem(SqList L, ElemType e)//使用Book类型的外号ElemType作为传入参数e的类型,使用int类型的外号Status作为函数的返回值类型
{
	for (int i = 0; i < L.length; i++)
	{
		//对比Book中的数据是否相等
		if (L.elem[i].name == e.name && L.elem[i].no == e.no && L.elem[i].price == e.price)
		{
			return i + 1;//因为线性表是从1开始的
		}
	}
	return 0;
}

/*
	顺序表的插入:时间复杂度为O(n)
	参数一:要插入的顺序表
	参数二:要插入的位置
	参数三:要插入的数据
	注意:成功:返回1;失败:返回0。
*/
Status ListInsert(SqList& L, int num, ElemType e)//使用Book类型的外号ElemType作为传入参数e的类型,使用int类型的外号Status作为函数的返回值类型
{
	if (L.length == MAXSIZE || num<1 || num >L.length + 1)//先判断输入是否合法
	{
		return 0;
	}
	for (int i = L.length - 1; i >= num - 1; i--)
	{
		L.elem[i + 1] = L.elem[i];
	}
	L.elem[num - 1] = e;
	L.length++;//成功插入数据,length长度+1
	return 1;
}

/*
	顺序表的删除:时间复杂度为O(n)
	参数一:要删除的顺序表
	参数二:要删除的位置
	注意:成功:返回1;失败:返回0。
*/
Status ListDelete(SqList& L, int num)//使用int类型的外号Status作为函数的返回值类型
{
	if (num<1 || num >L.length || L.length == 0)//先判断输入是否合法
	{
		return 0;
	}
	//这里书上是i < L.length-1;是错误的
	for (int i = num; i < L.length; i++)//删除数据就把num后的数据逐个前移,将其覆盖掉
	{
		L.elem[i-1] = L.elem[i];
	}
	L.length--;//成功删除数据,length长度-1
	return 1;
}

int main()
{
	SqList L;
	Book book;
	int temp = 0; //临时数据,用来判断执行是否成功
	cout << "======================================" << endl;
	cout << "1、初始化顺序表...";
	temp = InitList(L);
	if (!temp)
	{
		cout << "\t失败" << endl;
	}
	cout << "\t成功!" << endl;
	
	book.no = "978-7-115-37950-4";
	book.name = "数据结构(c语言版)(第2版)";
	book.price = 35;
	cout << "======================================" << endl;
	cout << "2、往顺序表中插入数据...";
	for (int i = 1; i <= 10; i++)
	{
		book.price = i;
		temp = ListInsert(L, i, book);
	}
	

	if (!temp)
	{
		cout << "\t失败" << endl;
	}
	cout << "\t成功!" << endl;
	cout << "======================================" << endl;
	/*cout << "3、扩容...";
	IncreaseSize(L, 5);
	cout << "L.MaxSize :"<< L.MaxSize << endl;*/
	cout << "3、获取图书的下标位置数据...";
	temp = LocateElem(L, book);
	if (!temp)
	{
		cout << "\t失败!" << endl;
	}
	cout << "\t成功!" << endl;
	cout << "--------------------------------------" << endl;
	cout << "下标位置为:" << temp << endl;
	Book book1;
	cout << "======================================" << endl;
	cout << "4、在顺序表中取得数据...";
	temp = GetElem(L, 1, book1);
	if (!temp)
	{
		cout << "\t失败" << endl;
	}
	cout << "\t成功!" << endl;
	cout << "--------------------------------------" << endl;
	cout << "图书信息为:" << endl;
	cout << "图书ISBN :" << book1.no
		<< "\t图书名称:" << book1.name
		<< "\t图书价格:" << book1.price << endl;
	cout << "======================================" << endl;
	cout << "5、删除顺序表中的数据...";
	temp = ListDelete(L, 5);
	if (!temp)
	{
		cout << "失败" << endl;
	}
	cout << "成功" << endl;
	cout << "======================================" << endl;
	for (int i = 1; i <= L.length; i++)
	{
		GetElem(L, i, book1);
		cout << book1.price << endl;
	}

	system("pause");
	return 0;
}

运行结果:

======================================
1、初始化顺序表...      成功!
======================================
2、往顺序表中插入数据...        成功!
======================================
3、获取图书的下标位置数据...    成功!
--------------------------------------
下标位置为:1
======================================
4、在顺序表中取得数据...        成功!
--------------------------------------
图书信息为:
图书ISBN :978-7-115-37950-4     图书名称:数据结构(c语言版)(第2版)  图书价格:35
======================================
5、删除顺序表中的数据...成功
======================================
请按任意键继续. . .
最后

当然,你也可以把程序改成switch类型的循环结构,以输入输出的形式执行程序。
以上为个人实践总结,如有错误和疏漏的地方,欢迎大佬评论区指正和补充…


觉得写还不错的话,还请点赞、收藏、评论和分享,非常感谢~


参考文献

  1. 《数据结构》C 语言版,严为敏 吴伟民编,清华大学出版社,2009.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值