数据结构_顺序表-1.19

学习内容

线性表

这相当于一种数据管理,你通过采集获得了一堆数据,这些数据你该怎么处理,提取出你需要的信息。
线性表就是其中的一种管理数据的形式:N个有相同特性的数据元素的有限序列。
(例如:顺序表(数组),链表(指针),栈,队列,字符串等)

1. 顺序表

从物理地址头开始连续的存储单元。

静态顺序表

#define N 100 
#typedef int SLDataType
typedef struct Seqlist
{
	SLDataType a[N];
	int size;
}SL;

这很像以前学的结构体,这样的信息汇总才更方便处理数据。
其中令人学习的点:
1)除了数据参数化,数据类型是不是也可以参数化?我可以用SLDataType 去选择我需要的数据类型。

2. 接口函数

这些天在一家公司的技术部里经常听到“接口”这个词,现在大体明白所谓接口函数,是你开发出来了功能后让客户去使用的地方就是接口。你输入数据,得到你想要的结果。
程序代码就是为了完成需求的
1)客户想给数据表后端添加数据:
void SeqlistPushBack(SL* p, SLDatatype x);//程序员就给你开发这个功能,然后给你这个数据x的接口去输入数据x

3. 动态顺序表(感觉不错)

按需分配是首选的。

#define N 100 
#typedef int SLDataType
typedef struct Seqlist
{
	SLDataType* a; 指定动态分配的起始地址
	int size;
	int capacity; 没有固定的内存大小,需要有个变量存储容量大小
}SL;

项目文件结构:
1)头文件定义一个顺序表(结构体)
2)test.c测试文件定义一个顺序表变量,并把顺序表起始地址传给定义文件
(我之前写的时候是把顺序表变量写在了定义文件中,现在回想,确实该写在test.c测试文件里(你要测试这个变量及其功能是否能实现),实现功能的定义文件只需要实现功能,你的顺序表变量相当于客户的需求(客户想改变修改他们给的变量))
3)Seqlist.c定义文件使用test.c传来的地址实现功能。

测试文件中,当遇到接口函数较多时,要单独写出测试函数分批次测试(算是个好习惯
(说实话,这些小细节的好习惯能有人讲一下是真的好,回想我的学习经历,能把这些经验教授予人的很少,要么是自己悟,要么别人不屑或是不想讲给你)
例如:

void TestSeqlist1()
{
	接口函数1;
	接口函数2}

4. 动态顺序表需要考虑的情况

1)顺序表本身是空的
2)你在执行操作后,内存空间不够了(改变了空间就需要考虑)
3)空间是足够的

a.本身空的和空间不够一起考虑
if (p->size == p->capacity)
	{
		int newcapacity = p->capacity == 0 ? 4 : p->capacity * 2;空的置4,不够翻倍
		p->capacity = newcapacity;
		SeqDataType* tmp = (SeqDataType*)realloc(p->a, p->capacity * sizeof(SeqDataType));
		if (tmp == 0) 开辟空间成功否?
		{
			printf("error");
			exit(-1);
		}
		p->a = tmp; 成功传给a

	}

上述值得学习的几点:
1)int newcapacity = p->capacity == 0 ? 4 : p->capacity * 2;
这句话就体现了代替if的“? :”表达式的优点,对这种一句话里的判断简洁明了。
除此,容量成倍增长,这种思路在TCP的congestion control里见过,指数增到collusion发生,再对半减,再加法增去尽快获得最恰当的大小。(这算算法吗?似乎是的,咱们作为使用者看起来没啥,从0到1又谈何容易?)(我个人极其反感中英文夹杂表达)
2)SeqDataType* tmp = (SeqDataType*)realloc(p->a, p->capacity * sizeof(SeqDataType));
最开始,我在想为什么不直接用“p->a”来开辟一段动态内存,反而用tmp来开辟。因为如果开辟失败了,p->a=NULL;你就直接丢失了原来的地址,这太可怕了,回不去了。所以要用tmp一个临时变量来试错,确认没错,再传给p->a。
(这里利用了realooc的memblock为Null等同于malloc的特性)
3)exit(-1)就是退出,之前是perror()。

你可能感兴趣的:(数据结构,学习,开发语言,c语言)