#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:
* 写程序不能使用最简模型,最好一直保持在通常情况
* 这样的代码才有通用性
*
*/
这是一次练习,慢慢体会关于线性表顺序存储的实例
最新推荐文章于 2022-10-21 20:46:40 发布