关于线性表顺序存储的实例

本文介绍了一个简单的线性表操作示例,包括初始化、插入、删除等基本操作,并通过具体的代码实现展示了如何管理和操作线性表。

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

#include <stdio.h>
#include <stdlib.h>
#define DATASIZE 1024
typedef int datatype;


typedef struct node_st
{
	datatype data[DATASIZE];
	int last;
}sqlist;


sqlist *sqlist_create();							//用于初始化的函数
void sqlist_create1(sqlist **ptr);						//第二种初始化
/*两种函数的区别在于:
*第一种:使用函数的返回值来传递
*第二种:利用二级指针直接取址来传递
*两种都是可行的
*/


void sqlist_display(sqlist *);							//遍历函数
int sqlist_insert(sqlist *, int i, datatype *);			                //线性表中的第i个位置插入操作
int sqlist_delete(sqlist *, int i);						//线性表中的第i个位置删除操作
void sqlist_destroy(sqlist *);							//销毁函数
int sqlist_find(sqlist *me, datatype *data);			                //查找函数
int sqlist_getnum(sqlist *);							//获取数字的个数
int sqlist_setempty(sqlist *);							//设置为空
int sqlist_isempty(sqlist *);							//判断是否为空表
int sqlist_union(sqlist *, sqlist *);					        //将两个链表合并


int main()
{
	sqlist *list = NULL, *list1 = NULL;					//先把指针写成空指针
	datatype arr[] = { 12, 23, 34, 45, 56 };
	datatype arr1[] = { 89, 90, 78, 67, 56, 45 };		                //第二个表
	list = sqlist_create();
	//sqlist_create1(&list)							//通过二级指针传参来返回地址


	//对于两种不同的初始化方式,所使用的处理方案相同
	if (list == NULL)
	{
		fprintf(stderr, "sqlist_create() failed!\n");
		exit(1);
	}


	//测试语句(打印行号 __LINE__):
	//printf("%d\n", __LINE__);


	list1 = sqlist_create();
	if (list1 == NULL)
	{
		fprintf(stderr, "create failed!\n");
		exit(1);
	}




	int err, i;
	for (i = 0;i < sizeof(arr) / sizeof(*arr);i++)
		if ((err = sqlist_insert(list, 0, &arr[i])) != 0)
		{
			//该情况是针对不正常情况处理
			//不同的err不同处理
			if (err == -1)
				fprintf(stderr, "The arr is full\n");
			else if (err == -2)
				fprintf(stderr, "The pos you want to insert is wrong\n");
			else
				fprintf(stderr, "Error!\n");


			exit(1);
		}


	//printf("%d\n", __LINE__);测试语句


	sqlist_display(list);


	for (int i = 0; i < sizeof(arr1) / sizeof(*arr1); i++)
	{
		sqlist_insert(list1, 0, &arr1[i]);
	}
	sqlist_display(list1);


	sqlist_union(list, list1);


	sqlist_display(list);


#if 0
	err = sqlist_delete(list, 1);
	if (err == -1)
		printf("错误,未能成功删除\n");


	sqlist_display(list);
#endif


	sqlist_destroy(list);
	sqlist_destroy(list1);


	exit(0);
}


sqlist *sqlist_create()
{
	sqlist *me;
	me = (sqlist *)malloc(sizeof(*me));


	/*如果申请失败,则返回了空即NULL,然后对于此种情况进行处理*/
	if (me == NULL)
		return NULL;
	me->last = -1;
	return me;
}


void sqlist_create1(sqlist **ptr)
{
	*ptr = (sqlist *)malloc(sizeof(**ptr));


	/*与上面的函数有点类似的处理方法
	*不同的是,这里的采用的是取址返回
	*而上个函数采用的是函数的返回值返回
	*/
	if (*ptr == NULL)
		return;
	(*ptr)->last = -1;   								//二级指针的一级目标
	return;
}


int sqlist_insert(sqlist *me, int i, datatype *data)
{
	//如果空间已满,返回错误代码-1表示失败
	if (me->last == DATASIZE - 1)
		return -1;


	//如果是其他异常,比如:
	//越界i < 0,已经超过数组最底端
	//i > last+1不是相邻的数据了,所以也是异常
	//此时返回错误代码-2
	if (i < 0 || i > me->last + 1)
		return -2;


	//临时变量存储last的值
	int j = me->last;


	//注:此时插入的时候应该是逆序往上插入而不是j++往下
	for (;i <= j;j--)
		//该步操作相当于把所有数据往下挪一位
		me->data[j + 1] = me->data[j];


	//挪完后,在i这个位置填入数据
	//下面的这一步操作只适用于常规的数据
	//如果是非常规的数据类型可能会造成赋值失败
	me->data[i] = *data;


	//传入完毕,序号自增
	me->last++;


	//如果上述异常都没有发生,返回正常代码0
	//注:一般来说,0表示程序无异常退出
	return 0;
}


void sqlist_display(sqlist *me)
{
	//该操作表示如果什么都没有就直接结束
	if (me->last == -1)
		return;
	int i;
	for (i = 0;i <= me->last;i++)
		printf("%d ", me->data[i]);
	printf("\n");
	return;
}


int sqlist_delete(sqlist *me, int i)
{
	//对于第i个元素的删除,不管怎么样,下面的情况是不能够出现的
	//如果出现,返回错误代码-1
	if (i < 0 || i > me->last)
		return -1;


	//对于删除操作,我们应该把后面所有的往前移一位
	//从编号低位往高位走
	int j;
	for (j = i + 1;j <= me->last;j++)
		me->data[j - 1] = me->data[j];


	//删除完毕,往前走一位
	me->last--;


	return 0;
}


int sqlist_find(sqlist *me, datatype *data)
{
	//如果为空的话,表示没有东西,直接返回
	if (sqlist_isempty(me) == 0)
		return -1;


	int i;
	for (i = 0;i < me->last;i++)
		if (me->data[i] == *data)
			return i;


	//如果没有找到任何相符的,返回-1表示失败
	return -2;
}


int sqlist_isempty(sqlist *me)
{
	//如果为-1表示last还没有动过,也就是没有数据
	if (me->last == -1)
		return 0;


	return -1;
}


int sqlist_getnum(sqlist *me)
{
	//对于有通用性的代码,就可以直接用
	return (me->last + 1);
}


int sqlist_setempty(sqlist *me)
{
	me->last = -1;
	return 0;
}


void sqlist_destroy(sqlist *me)
{
	free(me);
	return;
}


int sqlist_union(sqlist *list1, sqlist *list2)
{


	int i = 0;
	for (i = 0;i <= list2->last;i++)
	{
		if (sqlist_find(list1, &list2->data[i]) < 0)
		{
			//当作首部插入
			sqlist_insert(list1, 0, &list2->data[i]);
		}
	}


	return 0;
}
/*
* 收获 1:
* 作为一个程序,如果出了错误,应该慢慢调试
* 掐电路:
* 使用printf("%d", __LINE__);打印行号
* 来慢慢输出错误的地方
*
* 收获 2:
* 这个程序在编写代码的时候,和之前学语法面向过程的时候完全不同
* 对于某个函数,应该发挥什么样的功效,函数不急着实现
* 我们可以先架构好,命好名,每个函数只需要完成好自己的工作就行
* 对于每个函数而言不用担心其他的
* 和我之前做实训项目的时候有点像
* 当时我觉得每个函数实现自己功能即可,无需担心其他的
* 对于每个事物,有什么属性,应该怎么样打包
* 这就是面向对象编程
*
* 收获 2:
* 对于用户传递过来的操作参数,
* 能不改就不改,宁可多耗费一点点内存,也不要改动
*
* 收获 3:
* 写程序不能使用最简模型,最好一直保持在通常情况
* 这样的代码才有通用性
* 
*/
这是一次练习,慢慢体会

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值