C和指针读书笔记-第17章(经典抽象数据类型)

来源:互联网 发布:生产矩阵作业指导书 编辑:程序博客网 时间:2024/06/05 07:01

1.为ADT分配内存有三种技巧:静态数组、动态分配的数组和动态分配的链式结构。静态数组对结构施加预先确定固定长度的这个限制。动态数组的长度可以再运行时计算,如果需要数组也可以进行重新分配。链式结构对值的最大数量并未加以任何限制。

2.堆栈。后进先出。

堆栈提供三种接口:push,pop,top

top返回顶部元素的值,但它并不把顶部元素从堆栈中移除。

3.堆栈需要另外另个额外的函数:

需要一个函数告诉我们堆栈是否为空

如果堆栈存在最大长度限制,需要一个函数告诉我们堆栈是否已满。

4.在数组堆栈中,所有不属于外部接口的内容都被声明为static,这可以防止用户预定义接口之外的任何方式访问堆栈中的值。

变量top_element保存堆栈顶部元素的下标值。它的初始值为-1,提示堆栈为空。

5.动态数组实现堆栈。

要增加两个函数。

create_stack传经堆栈。参数指定堆栈可以保存多少个元素。

destroy_stack销毁堆栈,用于释放堆栈所使用的内存。避免内存泄露,这个函数式必须的。并且将对战的 长度改为0.

6.链式堆栈

不再需create_stack函数,但是可以实现destroy_stack用于清空堆栈

由于链式堆栈不会满,所以is_full函数始终返回假。


7队列

另外一种接口是,delete函数从队列的头部删除一个元素,但并不返回它,first函数返回队列第一个元素的值但并不将它从队列中删除。

链式和动态分配实现的队列需要使用的create_queue和destroy_queue函数的原型。

8.队列的实现需要两个指针。一个指向对头,一个指向队尾。

从队尾插入,从队头删除。

好的方案是让队列环绕到数组的头部,这样新元素就可以存储到以前删除元素所留出的空间中,这个方法常常被称为循环数组。

9

rear+=1;

if(rear>QUEUE_SIZE)

rear=0;

和 rear=(rear+1)%QUEUE_SIZE;效果一样。QUEUE是数组的大小,rear是最大指针,所以比QUEUE小1。例如a【5】其实最大指向是a【4】


10判断循环数组是否满和空。

重新定义满的含义。保留一个元素始终不用。

当队列满时,对头和队尾相差2.以前是相差1

当队列空时。当队列只有一个元素时,对头和队尾都指向这一个元素。为了能都指向这个元素,再插入后增加rear的值,当第一次插入后指向这个插入的元素。则队列为空时

rear的值必须比front小1.删除最后一个元素的情况也是如此。

这样空出一个元素,当队列为空的时候rear和front相差1.

删除最后一个元素后的状态是。也是相差1.

所以满足下列条件队列为空(rear+1)%QUEUE_SIZE==ront

满足下列条件队列为满:(rear+2)%QUEUE_SIZE==ront


11.链式队列,测试队列是否为空只是简单测试链表是否为空就可以了。


12树

二叉搜索树具有一个额外的属性,每个节点的值比它的左子树的所有节点的值都要大,但比它的右子树的所有节点的值都要小。

13.在二叉搜索树中插入,采用递归算法

14在二叉搜索树中删除节点。

如果删除的节点有两个孩子,则先删除它左子树中最大的那个节点,然后用这个值来替换原来的那个节点。

15.pre_order_traveres  它的参数是一个回调函数指针,它所指向的函数在树中处理每个节点被调用,节点的值作为参数传递给这个函数。

do_pre_order_rraveres


16. 链式搜索树。

find函数只用于验证树是否存在于这个树中。

把值插入到一个有序单链表有相同的技巧。

17.destory_tree用于四方所有分配给这棵树的内存。

18.用#define 宏实现代码,然后用目标类型进行扩展。或者通过把需要存储到ADT的值强制转换为void*。这种策略的缺点是它绕过了类型检查。

















0 0
原创粉丝点击