- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
在数组和哈希表上工作
在C语言中, 有两种不同的基础方法用来在一个结构体中存储任意数量的独立数据元素. 两种方法都有赞成者和反对者.
向量 Vs. 链表
应用的编写通常基于特定类型数据的特性的选择, 需要存储多少数据, 以及需要多快速度的检索. 为了能够有对等的认知, 我们先来看看简单的看看这些存储机制.
向量
向量是一块连续的内存空间, 它们包含的数据有规律的间隔. 向量最常见的例子就是字符串变量(char *或char []), 它包含了一个接着一个的字符(字节)序列.
char foo[4] = bar;
这里, foo[0]包含了字符b; 紧接着, 你将在foo[1]中找到字符a, 最后在foo[3]中是一个空字符\0.
将指向其他结构的指针存储到向量中的用法几乎是无所不在的, 比如在上一章, 使用zend_get_parameters_array_ex()函数时, 就使用了一个zval的向量. 那里, 我们看到var_dump()定义了一个zval ***的函数变量, 接着为它分配空间用来存储zval **指针(最终的数据来自zend_get_parameters_ex()调用)
zval ***args = safe_emalloc(ZEND_NUM_ARGS(), sizeof(zval**), 0);
和访问字符串中的数组一样, var_dump()实现中使用args[i]依次传递每个zval **元素到内部函数php_var_dump().
向量最大的优点在于运行时单个元素的访问速度. args[i]这样的变量引用, 可以很快的计算出它的数据地址(args + i * sizeof(args[0]). 这个索引结构的空间分配和释放是在单次, 高效的调用中完成的.
链表
另外一种常见的存储数据的方式是链表. 对于链表而言, 每个数据元素都是一个至少有两个属性的结构体: 一个指向链表中的下一个节点, 一个则是实际的数据. 考虑下面假设的数据结构:
typedef struct _namelist namelist;
struct {
struct namelist *next;
char *name;
} _namelist;
使用这个数据结构的引用需要定义一个变量:
static namelist *people;
链表中的第一个名字可以通过检查people变量的name属性得到: people-name; 第二个名字则访问next属性: people-next-name, 依此类推: people-next-next-name等等, 直到next为NULL表示链表中已经没有其他名字了. 更常见的用法是使用循环迭代链表:
void name_show(namelist *p)
{
while (p) {
printf(Name: %s\n, p-name);
p = p-next;
}
}
这种链表非常适合于FIFO的链式结构, 新的数据被追加到链表的末尾, 从另外一端线性的消耗数据:
static namelist *people = NULL, *last_person = NULL;
void name_add(namelist *person)
{
person-next = NULL;
if (!last_person) {
/* 链表中没有数据 */
people = last_person = person;
return;
}
/* 向链表末尾增加新的数据 */
last_person-next = person;
/* 更新链表尾指针 */
last_person = person;
}
namelist *name_pop(void)
{
namelist *first_person = people;
if (people) {
people = people-next;
}
return first_person;
}
新的namelist结构可以从这个链表中多次插入或弹出, 而不用调整结构的大小或在某些位置间块拷贝元素.
前面你看到的链表只是一个单链表, 虽然它有一些有趣的特性, 但它有致命的缺点. 给出链表中一项的指针, 将它从链中剪切出来并确保前面的元素正确的链接上下一个元素就变得比较困难.
为了知道它的前一个元素, 就需要遍历整个链表直到找到一个元素的next指针指向要被删除的元素. 对于大的链表, 这可能需要可观的CPU时间. 一个简单的相对廉价的解决方案是双链表.
对于双
您可能关注的文档
最近下载
- DB13(J)T 8486-2022 装配式建筑施工安全技术规范(京津冀).pdf VIP
- (高清版)DB3702∕T 37-2023基岩层序划分技术规范.pdf VIP
- DB13(J)T 8505-2022 历史建筑修缮与利用技术标准.pdf VIP
- DB13(J)T 8540-2023 地源热泵系统工程技术标准.pdf VIP
- J08J111 轻集料混凝土复合保温砌块填充外墙构造.pdf VIP
- 冀12G08 钢筋混凝土悬挑构件.pdf VIP
- 《新时代职业英语》教学资源_传媒英语_Unit_10_.pptx VIP
- 2024CSCO胃癌诊疗指南 .pdf VIP
- 光交箱规范指导手册.doc VIP
- JJF(蒙) 5013-2025 直流高压发生器校准规范.docx VIP
原创力文档


文档评论(0)