这是我的链表实现: 节点:
node struc
prev dw 0
next dw 0
data dw 0
node ends
此函数添加新节点:
tail - 指向链接列表尾部的指针
_data - 我们要追加的数据
node_add proc near c tail:word, _data_:word
mov bx,tail
mov ax,[bx]
.if ax==0 ;if there's no any nodes yet
;memory allocation; first param - count of blocks to be allocated second param would be segment address of blocks to be allocated
invoke mem_alloc,1,bx
push ds
mov ds,ax ;ds now contains segment address
mov ax, _data_ ;store data
mov [ds:node.data],ax
pop ds
.else ;if tail != 0, there's at least one node,we consider there was no error while memory allocation
push ds
mov ds,ax
invoke mem_alloc,1,node.next
push ds
mov ds,ax
mov ax,_data_
mov [ds:node.data],ax
;now we need to store list's tail to new list's tail previous node
pop ax
mov [ds:node.prev],ax
;now we need to update list's tail. We consider it's located in @data
mov ax,ds
pop ds
mov bx,tail
mov [bx],ax
.endif
ret
node_add endp
此函数删除节点:
_node - 要删除的节点
__ node - 偏向列表的尾部
__ node_seg - 列表尾部的段地址
mem_free - 释放内存,参数 - 要解除分配的块的地址
remove_node proc near c _node:WORD,__node:WORD,__node_seg:WORD
mov ax,_node
.if ax==0 ;if there's no any nodes
jmp exit
.endif
push ds
mov ds,_node
.if [ds:node.next]==0 ; if current node doesn't have next node
.if [ds:node.prev]==0 ; if current node doesn't have previous node
;so we have a single node, just remove it
invoke mem_free,_node
mov ax,__node_seg ;set node's tail to zero
mov ds,ax
mov [ds:__node],0
.else
;so we have have a standard sutiation when there's several nodes
push [ds:node.prev] ;go to previous node
pop ds
xor ax,ax ;we're about removing, so there's no next node anymore
mov [ds:node.next],ax
invoke mem_free,_node
;now update list's tail
push ds
mov ax,__node_seg
mov ds,ax
pop ax
mov bx,__node
mov [bx],ax
.endif
.else
.if [ds:node.prev]==0
;so node to be deleted is first node
push [ds:node.next];go to next node
pop ds
xor ax,ax ;;we're about removing, so there's no previous node anymore
mov [ds:node.prev],ax
invoke mem_free,_node
.else
;yet another situation, node to be deleted is located between two another ones
mov cx,[ds:node.next]
mov dx,[ds:node.prev]
mov ds,dx
mov [ds:node.next],cx
mov ds,cx
mov [ds:node.prev],dx
invoke mem_free,_node
.endif
.endif
exit:
pop ds
Ret
remove_node endp
现在假设我们从尾部
开始遍历所有节点push ds
mov cx,node_count ;located in @data
mov ax,node_tail
mov ds,ax
.while cx>0
.if (SOME_CONDITION)
(some actions)
;we're about node removing, and we need to set ds to previous node
mov ax,[ds:node.prev]
push ax
mov bx,@data
push cx
invoke remove_node,ds,offset tail,bx
pop cx
pop bx
mov ax,@data
mov ds,ax
dec node_count
mov ds,bx
jmp __label
.endif
(some actions)
;otherwise just go to next node
mov ax,[ds:node.prev]
mov ds,ax
__label:
dec cx
.endw
问题在于有时某个节点具有相同的node.prev和node.next,有时一个节点可以指向自身!
此代码适用于MS-DOS。