把所有指针集中到一起,构成图结构,放在数组里。如何写链表呢?C语言实现的数据结构,习惯把next指针放在data旁边。要改变这一现状。先分配一块内存记录数据,再从图结构里添加一个节点。节点和内存块一一对应。怎样表示图结构?每个节点有3个成员,分别是 内存块的首地址、子节点、兄弟节点。
空白节点构成一个链表,首地址=NULL,子节点当做next,兄弟节点待定。是否应该用C语言的共用体实现?节点保存在数组中,遍历时,从数组的第一个元素开始,a[0]是根节点,不能删除。所有空闲的堆内存在数组中都有对应的节点?这也是如何表示空闲内存的方法,每块空闲内存都对应一个节点,这些节点组成链表。分配内存时,依次扫描链表,找到适当大小的一块空闲内存。
空白节点和空闲内存不同,空闲内存对应于节点数组中的有效节点,其特点是首地址项≠NULL;而空白节点是数组中尚未使用的项目,本来应该指向堆内存的首地址=NULL。
当所有指针集中到一起后,可以进行指针的搜索。以前必须用双链表解决的问题,现在用单链表。一个指针,从A指向B,在A处能知道它指向了B,但是在B处却不知道谁指向了自己。以前遇到这类问题,用两个指针解决,即单链表变成双链表。有了指针搜索功能后,不必这样了。
垃圾回收的标准是,某节点,没有节点指向它,则该节点为可回收节点。应该释放该节点,和它对应的堆内存。我想到一个笨方法,由于0号节点表示根节点,所以跳过它,从1号节点开始,如果1号节点的首地址≠NULL,这表明它是一个有效节点,遍历节点数组,看有没有哪个指针指向它,如果有则进行下一个节点,如果没有则按照垃圾节点处理。处理完节点数组中的所有节点后,即完成了一次垃圾回收。这个方法太慢了,若节点数组中有N项,则需N2次操作。不过每次操作倒是时间都不长,即使这样也不成,太慢。
方法二,把指针数组里的有效节点都加入哈希表,然后就能快速地判断某地址在不在其中。这个方法肯定能快不少。时间复杂度从n2降到了2n。
关于0号节点有没有兄弟节点,我想,完全可以有。画出图来,它们是几个独立的图结构,都有效。没有理由拒绝这个功能。
不能删除0号节点,也不应该指向0号节点。为什么?因为它就是这么特殊。
上文中总是叫“节点数组”,应该叫指针段,并期待CPU能支持这个段寄存器。到时候,有代码段、指针段、数据段(纯数据,没有指针)、栈也是一个段。输入法里都没有“指针段”这个词,看来我又超前了。
数据结构的课本里没有兄弟节点,着重讲解一下。设节点A有3个子节点b c d,则b c d是兄弟关系,它们构成一个链表,A的子节点是b,并且由b指出所有的b c d。节点数组是一个3列多行的表,3列分别是(堆内存中的首地址 子节点 兄弟节点)。设计中它们应该是64+32+32比特,设想不会有超过232个节点出现。这一想法是为了省内存,如果不在乎,都用64比特也可以。在数组中表示链表、图等结构,子节点和兄弟节点中记录的是绝对地址还是相对地址?采用绝对地址速度更快,采用相对地址(即数组下标)便于理解,但速度略慢,这是p和a[i]的速度差。另外一点不同,采用相对地址的节点数组可以复制、移动,绝对地址则不行。