前言
首先,感谢勇芳为我们提供了强大的编辑器vfb。这是我在csdn上第一次发关于freebasic的博客。因为我是一名初三学生,没有时间系统学习fb,以下代码有不规范的还请各位大佬指出[真诚]
(转载请标明出处)
百度百科对链表的定义
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
单链表的模型
单链表模型如下图所示[图片来自网络]
实现思路
freebasic支持指针,但又不像C++支持new关键字,刚开始,我想用调用API申请堆内存的方法实现,但此种方法过于繁琐。联系到fb支持调用c函数的特点,我想到了malloc函数。
我们定义链表节点类型为LNode,包括一个_next指针和数据域data。用malloc函数每次申请大小为sizeof(LNode)的内存,通过List_Create()方法生成链表头指针pHead,之后就可以愉快的进行各种方法的编写了
malloc函数讲解
百度上对malloc的解释比较生僻难懂,这里我讲解一下我的思路。malloc就是动态地申请一块指定大小内存,并返回其指针(void指针)。因为是void*类型,如果我们想操作这块内存就要进行类型转换,也就要用到Cast(欲转换成的类型,变量)将void指针转换成LNode ptr。
想要使用malloc必须包含以下库
#Include Once "crt\stdlib.bi"
LNode类型
Type LNode
_data As Long
_next As LNode Ptr
End Type
List_Create()的实现
先上代码
Function List_Create() As LNode Ptr
Dim As LNode Ptr pHead,pTail
pHead = Cast(LNode Ptr, malloc(SizeOf(LNode)))
If (pHead = Null) Then
List_Create = Null
End If
pTail = pHead
pTail-> _next = Null
List_Create = pTail
End Function
首先定义头指针,并为其申请内存空间,pHead=Null是对malloc是否申请成功的特判,其实这里的Ptail指针完全不需要(尾指针的next为Null),这里这样写是为了让大家更好地理解这个过程(链表头指针与尾指针重叠,链表为空)
List_AddNode(_data)的实现
与Create函数原理类似,此函数是向链表尾部添加一个节点。
Function List_AddNode(pHead As LNode Ptr, _data As Long) As BOOL
Dim As LNode Ptr p
Dim As LNode Ptr newN
p = pHead
Do While p-> _next <> Null
p = p-> _next
Loop
newN = Cast(LNode Ptr, malloc(SizeOf(LNode)))
newN-> _data = _data
newN-> _next = p-> _next
p-> _next = newN
List_AddNode =True
End Function
先通过一个while循环获取尾指针,再将尾指针的next指向新节点,新节点的next赋值为Null,将数值data存进新节点。大功告成。
List_DeleteAll(pHead)的实现
有创造就有销毁,此函数的功能是释放所有链表节点。
Function List_DeleteAll(pHead As LNode Ptr) As BOOL
Dim As LNode Ptr p,q
p = pHead-> _next
q = pHead
free(q)
Do While p-> _next <> Null
q = p
p = p-> _next
free(q)
Loop
free(p)
List_DeleteAll =True
End Function
感谢强大的C,我们再次需要调用C函数。free()函数的作用就是释放一个指针。这里通过循环逐个释放,其余原理同上,不过多解释。
List_InsertNode(pHead,id,_data)的实现
将_data插入指定链表的第id位置
Function List_InsertNode(pHead As LNode Ptr, id As Long, _data As Long) As BOOL
Dim As LNode Ptr p=pHead
Dim As Long i
For i = 1 To id -1
p = p-> _next
Next i
Dim As LNode Ptr q
q = p
Dim As LNode Ptr inode
inode = Cast(LNode Ptr, malloc(SizeOf(LNode)))
p = p-> _next
inode-> _next = p
q-> _next = inode
inode-> _data = _data
List_InsertNode = True
End Function
这里我主要讲解一下插入的过程。因为要插入到id位置,也就是向第id-1个节点后插入(在第id个节点前插入)。所以,我们先用循环获取第id-1个节点的指针,并用指针q存下,再获取当前第id个节点的指针。新节点的next指针指向p,q的next指向inode,此时inode节点即为第id个节点。
List_DeleteNode(pHead,id)的实现
删除指定位置的节点,原理互逆
Function List_DeleteNode(pHead As LNode Ptr, id As Long) As BOOL
Dim As LNode Ptr p=pHead
Dim As Long i
For i = 1 To id-1
p = p-> _next
Next i
If p = Null Then
Return False
End If
Dim As LNode Ptr q
q = p
p = p-> _next
q-> _next = p-> _next
free(p)
List_DeleteNode =True
End Function
拓展:获得链表长度函数的实现
遍历一遍,即可得出长度
Function List_GetLength(pHead As LNode Ptr) As Long
Dim As LNode Ptr p=pHead
Dim As Long i
i = 0
Do While p-> _next <> Null
p = p-> _next
i=i+1
Loop
List_GetLength = i
End Function
总结
当然,这里还有很多功能我没有实现(比如find函数),特殊情况的判断也不全面,但原理都是一致的。希望广大fb爱好者能在我的基础上完善链表的操作,同时提高编程技术。