freebasic.net Forum Index
FreeBASIC's Official Forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister   ProfileProfile   Log inLog in

Just Another Linked List...
Goto page 1, 2  Next
 
Post new topic   Reply to topic    freebasic.net Forum Index -> Tips and Tricks
View previous topic :: View next topic  
Author Message
krcko

PostPosted: Oct 17, 2006 18:22    Post subject: Just Another Linked List... Reply with quote

i was playing with macros and overloaded functions and made another linked list implementation...

the approach i'we used here alows making lists of any data type (udts or scalar types) but you can't mix different types in one list, anyway here's the code:

jall.bas:
Code:

'
' -------------------------------------------------
'
'   JALL - Just Another Linked List
'
'   by Aleksandar Ruzicic (admin@krcko.net)
'
'   Feel free to use this if you like it, just:
'   "give credit where credit is due" :)
'
' -------------------------------------------------
'

#ifndef __JALL_BAS__
   
    #define __JALL_BAS__
   
    Option Explicit
       
    Declare Sub ListAdd Overload ()
    Declare Sub ListRemove Overload ()
    Declare Function ListItem Overload () As Byte
    Declare Sub ListSet Overload ()
    Declare Sub ListPush Overload ()
    Declare Function ListPop Overload () As Byte
    Declare Sub ListClear Overload ()
    Declare Sub ListResizeItem Overload ()
       
    Sub ListAdd(): End Sub
    Sub ListRemove(): End Sub
    Function ListItem() As Byte: Return 0: End Function
    Sub ListSet(): End Sub
    Sub ListPush(): End Sub
    Function ListPop() As Byte: Return 0: End Function
    Sub ListClear(): End Sub
    Sub ListResizeItem(): End Sub
   
    #Macro DefineListType( __TYPE__ )
       
        #ifndef __JALL__LIST__TYPE__##__TYPE__##__DEFINED__
           
            #define __JALL__LIST__TYPE__##__TYPE__##__DEFINED__
           
            Type __TYPE__##ListItem
               
                p_data  As __TYPE__ Pointer
                p_next  As __TYPE__##ListItem Pointer
                p_prev  As __TYPE__##ListItem Pointer
                   
            End Type
           
            Type __TYPE__##List
               
                p_first As __TYPE__##ListItem Pointer
                p_last  As __TYPE__##ListItem Pointer
                Count   As Integer
           
            End Type
           
            Declare Sub ListAdd(Byref List As __TYPE__##List, Byref Item As __TYPE__)
            Declare Sub ListRemove(ByRef List As __TYPE__##List, ByRef Index As Integer)
            Declare Function ListItem(Byref List As __TYPE__##List, Index As Integer) As __TYPE__
            Declare Sub ListSet(Byref List As __TYPE__##List, Index As Integer, Byref Item As __TYPE__)
            Declare Sub ListPush(Byref List As __TYPE__##List, Byref Item As __TYPE__)
            Declare Function ListPop(Byref List As __TYPE__##List) As __TYPE__
            Declare Sub ListClear(Byref List As __TYPE__##List)
            Declare Sub ListResizeItem(Byref List As __TYPE__##List, Index As Integer, Item As __TYPE__)
           
            Sub ListAdd(Byref List As __TYPE__##List, Byref Item As __TYPE__)
               
                Dim tmp As __TYPE__##ListItem Pointer
               
                tmp = Callocate(Len(__TYPE__##ListItem))
               
                tmp->p_data = Callocate(Len(__TYPE__))
                *tmp->p_data = Item
               
                List.Count += 1
               
                If List.p_first = 0 Then
                   
                    List.p_first = tmp
                    List.p_last = tmp
                   
                Else
                   
                    tmp->p_prev = List.p_last
                    List.p_last->p_next = tmp                   
                    List.p_last = tmp

                End If                 
               
            End Sub
           
            Sub ListRemove(ByRef List As __TYPE__##List, ByRef Index As Integer)
               
                If Index > 0 And Index <= List.Count Then
                   
                    Dim As __TYPE__##ListItem Pointer item = List.p_first, nextItem, prevItem
                    Dim i As Integer
                   
                    For i = 1 To Index - 1
                        item = item->p_next
                    Next
                   
                    nextItem = item->p_next
                    prevItem = item->p_prev
                   
                    If nextItem <> 0 Then nextItem->p_prev = prevItem
                    If prevItem <> 0 Then prevItem->p_next = nextItem
                   
                    If List.p_first = item Then List.p_first = nextItem
                    If List.p_last = item Then List.p_last = prevItem
                   
                    Deallocate(item->p_data)
                    Deallocate(item)
                   
                    List.Count -= 1
                   
                End If
               
            End Sub
           
            Function ListItem(Byref List As __TYPE__##List, Index As Integer) As __TYPE__
               
                If Index > 0 And Index <= List.Count Then
                   
                    Dim As __TYPE__##ListItem Pointer item = List.p_first
                    Dim i As Integer
                   
                    For i = 1 To Index - 1
                        item = item->p_next
                    Next
                   
                    Return *item->p_data
                       
                End If
               
               
            End Function
           
            Sub ListSet(Byref List As __TYPE__##List, Index As Integer, Byref Item As __TYPE__)
               
                If Index > 0 And Index <= List.Count Then
                   
                    Dim As __TYPE__##ListItem Pointer tmp = List.p_first
                    Dim i As Integer
                   
                    For i = 1 To Index - 1
                        tmp = tmp->p_next
                    Next
                   
                    *tmp->p_data = Item
                   
                End If
               
            End Sub
           
            Sub ListPush(Byref List As __TYPE__##List, Byref Item As __TYPE__)
               
                Dim As __TYPE__##ListItem Pointer tmp, nextItem
               
                List.Count += 1
               
                tmp = Callocate(Len(__TYPE__##ListItem))
               
                tmp->p_data = Callocate(Len(__TYPE__))
                *tmp->p_data = Item
               
                nextItem = List.p_first
               
                List.p_first = tmp
               
                If nextItem <> 0 Then
                   
                    nextItem->p_prev = tmp
                    List.p_first->p_next = nextItem
               
                Else
                   
                    List.p_last = tmp
                   
                End If
               
            End Sub
           
            Function ListPop(Byref List As __TYPE__##List) As __TYPE__
               
                If List.Count > 0 Then
                   
                    Dim As __TYPE__ Result = ListItem(List, List.Count)
                   
                    ListRemove(List, List.Count)
                   
                    Return Result
               
                End If
           
            End Function
           
            Sub ListClear(Byref List As __TYPE__##List)
               
                If List.Count > 0 Then
                   
                    Dim As __TYPE__##ListItem Pointer item1, item2
                   
                    item1 = List.p_first
                   
                    While item1 <> 0
                       
                        item2 = item1
                        item1 = item1->p_next
                       
                        Deallocate(item2->p_data)
                        Deallocate(item2)
                       
                    Wend
                   
                    List.Count = 0
                   
                End If
               
            End Sub
           
            Sub ListResizeItem(Byref List As __TYPE__##List, Index As Integer, Item As __TYPE__)
               
                If Index > 0 And Index <= List.Count Then
                   
                    Dim As __TYPE__##ListItem Pointer tmp = List.p_first
                    Dim i As Integer
                   
                    For i = 1 To Index - 1
                        tmp = tmp->p_next
                    Next
                   
                    tmp->p_data = Reallocate(tmp->p_data, Len(Item))
                   
                    *tmp->p_data = Item
                   
                End If
               
            End Sub
           
        #endif
       
    #EndMacro
   
#endif
 


test.bas:
Code:

   
    #include "jall.bas"
   
   
    Type UDT
        i   As Integer
        d   As Double
    End Type
   
    Dim i As Integer ' counter in loops
    Dim u As UDT ' used in debugUDT macro
   
    #Macro debugList(__lst__)
       
        Print #__lst__; " items:"
       
        For i = 1 To __lst__.Count
       
            Print i; ": "; ListItem(__lst__, i)
       
        Next
       
        Print ""
       
    #EndMacro
   
    #Macro debugUDT(__lst__)
       
        Print #__lst__; " items:"
       
        For i = 1 To __lst__.Count
           
            u = ListItem(__lst__, i)
           
            Print i; ": "; u.i; ", "; u.d
           
        Next
       
        Print ""
       
    #EndMacro
   
    DefineListType(Integer) ' define IntegerList
    DefineListType(String)  ' define StringList
    DefineListType(UDT)     ' define UDTList
   
    ' declare lists
    Dim list1 As IntegerList
    Dim list2 As StringList
    Dim list3 As UDTList
   
    ' declare some variables
    Dim v1 As Integer
    Dim v2 As String
    Dim v3 As UDT
   
    ''' integer list '''
   
    ' adding integers to list1
    For i = 0 To 19
        ListAdd(list1, i)
    Next
   
    debugList(list1)
   
    ' clear list1
    ListClear(list1)
   
    v1 = 42
   
    ' push some data into list1
    ListPush(list1, 1)
    ListPush(list1, 10)
    ListPush(list1, v1)
    ListPush(list1, 88)
   
    debugList(list1)
   
    v1 = 18 ' change variable's value
   
    debugList(list1) ' nothing changed!
   
    ' change value of list item with index 2
    ListSet(list1, 2, 18)
   
    debugList(list1)
   
    ' remove item with index 3
    ListRemove(list1, 3)
   
    debugList(list1)
   
    ' pop value
    Print "popped: "; ListPop(list1)
    Print
   
    debugList(list1)
   
   
    ''' string list '''
   
    ' fill list2 with some values:
    v2 = "blah"
   
    ListPush(list2, "foo")
    ListPush(list2, v2)
    ListPush(list2, "bar")
   
    debugList(list2)
   
    v2 = "this is changed"
   
    debugList(list2)
   
    ListResizeItem(list2, 2, "this is changed") ' safer to use than ListSet (when working with strings), i think
   
    debugList(list2)
   
    For i = 1 To list2.Count
       
        Print "popped: "; ListPop(list2)
           
    Next
   
    Print
   
    ListAdd(list2, "item1")
    ListAdd(list2, "item2")
    ListAdd(list2, "item3")
   
    debugList(list2)
   
    ListAdd(list2, "added")
    ListPush(list2, "pushed")
   
    debugList(list2)
   
   
    ''' udt list '''
   
    ListAdd(list3, Type<UDT>(1, 0.5))
    ListAdd(list3, Type<UDT>(0, 3.14))
    ListAdd(list3, Type<UDT>(123, 48.58565))
    ListAdd(list3, Type<UDT>(448, 45680.5654))
   
    debugUDT(list3)
   
    v3.i = 20
    v3.d = 5.6987
   
    ListPush(list3, v3)
   
    debugUDT(list3)
   
    v3.i = 345
   
    debugUDT(list3)
   
    ListSet(list3, 1, Type<UDT>(345, 5.6987))
   
    debugUDT(list3)
   
    Sleep
 


i've tested this with 0.17b testing july/30 version...

p.s. i'm still learning fb...
 
Back to top
View user's profile Send e-mail Visit poster's website MSN Messenger
Imortis
Master
PostPosted: Oct 18, 2006 12:17    Post subject: Reply with quote

Nice Job. Doubly Linked list, eh? I tried to do a single but couldn't figure out how to safely remove a node. You have done better than I did. May I *barrow* this for learning purposes?
 
Back to top
View user's profile Send e-mail Visit poster's website AIM Address Yahoo Messenger MSN Messenger
relsoft
Master
PostPosted: Oct 18, 2006 13:58    Post subject: Reply with quote

Imortis wrote:
Nice Job. Doubly Linked list, eh? I tried to do a single but couldn't figure out how to safely remove a node. You have done better than I did. May I *barrow* this for learning purposes?


wrote this on top of my head, so this may not be sound.

Code:
temp = current->next
temp2 = current
current = current->prev
current ->next = temp
deallocate  temp2
 
 
Back to top
View user's profile Visit poster's website Yahoo Messenger
krcko

PostPosted: Oct 18, 2006 14:54    Post subject: Reply with quote

Imortis wrote:
Nice Job. Doubly Linked list, eh? I tried to do a single but couldn't figure out how to safely remove a node. You have done better than I did. May I *barrow* this for learning purposes?

thanks, offcourse you can *barrow* the code :) that's way i posted it, so others can use it and/or learn something from it (i'm begginer in fb and i've wrote this just to learn some new things like pointers and alloc/dealloc stuff...)

about single linked lists, maybe something like this will do when removing of node is needed (not tested):
Code:

Type SLLItem
  p_data As Any Pointer
  p_next As SLLItem Pointer
End Type

Type SLL
  p_root As SLLItem Pointer
  Count As Integer
End Type

Sub ListRemove(ByRef List As SLL, Index As Integer)
  If Index > 0 And Index <= List.Count Then
     
        Dim i As Integer 
        Dim As SLLItem Pointer node = List.p_root, prev

       For i = 1 To Index - 1
          prev = node
          node = node->p_next
       Next

       prev->p_next = node->p_next
       
       ' deallocate node->p_data if needed
       Deallocate(node)

  End If
End Sub
 
 
Back to top
View user's profile Send e-mail Visit poster's website MSN Messenger
krcko

PostPosted: Oct 18, 2006 20:37    Post subject: Reply with quote

i've downloaded latest version from cvs and played with new features...

and this is what i've made of JALL (it's YALL now :D):

yall.bas:
Code:

'
' -------------------------------------------------------------------------
'
'   YALL - Yet Another Linked List
'
'   by Aleksandar Ruzicic (admin@krcko.net)
'
'   Feel free to use this if you like it, just:
'   "give credit where credit is due" :)
'
' -------------------------------------------------------------------------
'
'  Usage:
'
'  #include "yall.bas"
'
'
'  defineListType(String)  ' StringList data type is now available
'
'  Dim list As StringList
'
'  list.add("item 1")
'  list.add("item 2")
'  list.add("item 3")
'
'   ...
'
'  Properties:
'
'   <DataTypeList>.Count As Integer
'    - returns length of list (number of items)
'
'
'  Methods:
'
'  Sub <DataTypeList>.Add(ByRef Item As <DataType>)
'   - adds item to the end of list
'
'  Sub <DataTypeList>.Remove(Index As Integer)
'   - removes item at Index position
'
'  Function <DataTypeList>.GetItem(Index As Integer) As <DataType>
'   - returns item from Index position
'
'  Sub <DataTypeList>.Set(Index As Integer, Item As <DataType>)
'   - changes value of item at Index position
'
'  Sub <DataTypeList>.Push(ByRef Item As <DataType>)
'   - adds item to the top of list
'
'  Function <DataTypeList>.Pop() As <DataType>
'   - returns value of the item from the top of the list, and removes it
'
'  Function <DataTypeList>.PopBack() As <DataType>
'   - returns value of the item from the bottom of the list, and removes it
'
'  Sub <DataTypeList>.Clear()
'   - removes all items from the list
'
'  Sub <DataTypeList>.ResizeItem(Index As Integer, Item As <DataType>)
'   - changes value of the item as Index position and Reallocates memory
'     needed to store item value (recomended to use with dynamic-length
'     strings, instead of .Set)
' -------------------------------------------------------------------------

#ifndef __YALL_BAS__
   
    #define __YALL_BAS__
   
    #macro DefineListType( __TYPE__ )
       
        #ifndef __YALL__LIST__TYPE__##__TYPE__##__DEFINED__
           
            #define __YALL__LIST__TYPE__##__TYPE__##__DEFINED__
           
            Type __TYPE__##ListItem
               
                p_data  As __TYPE__ Pointer
                p_next  As __TYPE__##ListItem Pointer
                p_prev  As __TYPE__##ListItem Pointer
                   
            End Type
           
            Type __TYPE__##List
               
                p_first As __TYPE__##ListItem Pointer
                p_last  As __TYPE__##ListItem Pointer
                Count   As Integer
               
                Declare Sub Add(Byref Item As __TYPE__)
                Declare Sub Remove(ByRef Index As Integer)
                Declare Function GetItem(Index As Integer) As __TYPE__
                Declare Sub Set(Index As Integer, Byref Item As __TYPE__)
                Declare Sub Push(Byref Item As __TYPE__)
                Declare Function Pop() As __TYPE__
                Declare Function PopBack() As __TYPE__
                Declare Sub Clear()
                Declare Sub ResizeItem(Index As Integer, Item As __TYPE__)
               
            End Type
           
           
            Sub __TYPE__##List.Add(Byref newItem As __TYPE__)
               
                Dim tmp As __TYPE__##ListItem Pointer
               
                tmp = Callocate(Len(__TYPE__##ListItem))
               
                tmp->p_data = Callocate(Len(__TYPE__))
                *tmp->p_data = newItem
               
                This.Count += 1
               
                If This.p_first = 0 Then
                   
                    This.p_first = tmp
                    This.p_last = tmp
                   
                Else
                   
                    tmp->p_prev = This.p_last
                    This.p_last->p_next = tmp                   
                    This.p_last = tmp

                End If                 
               
            End Sub
           
            Sub __TYPE__##List.Remove(ByRef Index As Integer)
               
                If Index > 0 And Index <= This.Count Then
                   
                    Dim As __TYPE__##ListItem Pointer item = This.p_first, nextItem, prevItem
                    Dim i As Integer
                   
                    For i = 1 To Index - 1
                        item = item->p_next
                    Next
                   
                    nextItem = item->p_next
                    prevItem = item->p_prev
                   
                    If nextItem <> 0 Then nextItem->p_prev = prevItem
                    If prevItem <> 0 Then prevItem->p_next = nextItem
                   
                    If This.p_first = item Then This.p_first = nextItem
                    If This.p_last = item Then This.p_last = prevItem
                   
                    Deallocate(item->p_data)
                    Deallocate(item)
                   
                    This.Count -= 1
                   
                End If
               
            End Sub
           
            Function __TYPE__##List.GetItem(Index As Integer) As __TYPE__
               
                If Index > 0 And Index <= This.Count Then
                   
                    Dim As __TYPE__##ListItem Pointer item = This.p_first
                    Dim i As Integer
                   
                    For i = 1 To Index - 1
                        item = item->p_next
                    Next
                   
                    Return *item->p_data
                       
                End If
               
               
            End Function
           
            Sub __TYPE__##List.Set(Index As Integer, Byref Item As __TYPE__)
               
                If Index > 0 And Index <= This.Count Then
                   
                    Dim As __TYPE__##ListItem Pointer tmp = This.p_first
                    Dim i As Integer
                   
                    For i = 1 To Index - 1
                        tmp = tmp->p_next
                    Next
                   
                    *tmp->p_data = Item
                   
                End If
               
            End Sub
           
            Sub __TYPE__##List.Push(Byref Item As __TYPE__)
               
                Dim As __TYPE__##ListItem Pointer tmp, nextItem
               
                This.Count += 1
               
                tmp = Callocate(Len(__TYPE__##ListItem))
               
                tmp->p_data = Callocate(Len(__TYPE__))
                *tmp->p_data = Item
               
                nextItem = This.p_first
               
                This.p_first = tmp
               
                If nextItem <> 0 Then
                   
                    nextItem->p_prev = tmp
                    This.p_first->p_next = nextItem
               
                Else
                   
                    This.p_last = tmp
                   
                End If
               
            End Sub
           
            Function __TYPE__##List.Pop() As __TYPE__
               
                If This.Count > 0 Then
                   
                    Dim As __TYPE__ Result
                    Dim As __TYPE__##ListItem Pointer nextItem
                   
                    Result = *This.p_first->p_data
                   
                    nextItem = This.p_first->p_next
                   
                    Deallocate(This.p_first->p_data)
                    Deallocate(This.p_first)
                   
                    This.p_first = nextItem
                    This.p_first->p_prev = 0
                   
                    This.Count -= 1
                   
                    Return Result
                   
                End If
           
            End Function
           
            Function __TYPE__##List.PopBack() As __TYPE__
               
                If This.Count > 0 Then
                   
                    Dim As __TYPE__ Result
                    Dim As __TYPE__##ListItem Pointer prev
                   
                    Result = *This.p_last->p_data
                   
                    prev = This.p_last->p_prev
                   
                    Deallocate(This.p_last->p_data)
                    Deallocate(This.p_last)
                   
                    This.p_last = prev
                    This.p_last->p_next = 0
                   
                    This.Count -= 1
                   
                    Return Result
                   
                End If
           
            End Function
           
            Sub __TYPE__##List.Clear()
               
                If This.Count > 0 Then
                   
                    Dim As __TYPE__##ListItem Pointer item1, item2
                   
                    item1 = This.p_first
                   
                    While item1 <> 0
                       
                        item2 = item1
                        item1 = item1->p_next
                       
                        Deallocate(item2->p_data)
                        Deallocate(item2)
                       
                    Wend
                   
                    This.Count = 0
                   
                End If
               
            End Sub
           
            Sub __TYPE__##List.ResizeItem(Index As Integer, Item As __TYPE__)
               
                If Index > 0 And Index <= This.Count Then
                   
                    Dim As __TYPE__##ListItem Pointer tmp = This.p_first
                    Dim i As Integer
                   
                    For i = 1 To Index - 1
                        tmp = tmp->p_next
                    Next
                   
                    tmp->p_data = Reallocate(tmp->p_data, Len(Item))
                   
                    *tmp->p_data = Item
                   
                End If
               
            End Sub
           
        #endif
       
    #endmacro
   
#endif
 


and simple test:
Code:

   
    #include "yall.bas"
   
   
    Dim i As Integer
           
    #macro debug(__list__)
        For i = 1 To __list__.Count
            Print i; ": "; __list__.GetItem(i)
        Next
        Print ""
    #endmacro
   
    defineListType(String)
   
    Dim As StringList test
   
    test.push "foo"
    test.push "blah blah blah"
    test.push "bar"
   
    debug(test)
   
    test.push "pushed"
    test.add "added"
   
    debug(test)
   
    Print "popped: "; test.pop
    Print
    Print "back-popped: "; test.popback
    Print
   
    debug(test)
   
    test.Remove 2
   
    debug(test)
   
    test.set 1, "foo"
    test.set 2, "bar"
   
    debug(test)
   
    test.clear
   
    Sleep
 
 
Back to top
View user's profile Send e-mail Visit poster's website MSN Messenger
gedumer

PostPosted: Oct 19, 2006 22:07    Post subject: Reply with quote

I get the following errors:

Code:

C:\FreeBASIC\FB_17>fbc testyall.bas
testyall.bas(15) : Error 18: Syntax Error, found: 'Sub'

    DefineListType(String)
                          ^
testyall.bas(15) : Error 18: Syntax Error, found: 'Sub'

    DefineListType(String)
                          ^
testyall.bas(15) : Error 18: Syntax Error, found: 'Function'

    DefineListType(String)
                          ^
testyall.bas(15) : Error 18: Syntax Error, found: 'Sub'

    DefineListType(String)
                          ^
testyall.bas(15) : Error 18: Syntax Error, found: 'Sub'

    DefineListType(String)
                          ^
testyall.bas(15) : Error 18: Syntax Error, found: 'Function'

    DefineListType(String)
                          ^
testyall.bas(15) : Error 18: Syntax Error, found: 'Function'

    DefineListType(String)
                          ^
testyall.bas(15) : Error 18: Syntax Error, found: 'Sub'

    DefineListType(String)
                          ^
testyall.bas(15) : Error 18: Syntax Error, found: 'Sub'

    DefineListType(String)
                          ^
testyall.bas(15) : warning level 0: Implicit variable allocation, This.p_first
testyall.bas(15) : warning level 0: Implicit conversion
testyall.bas(15) : warning level 0: Implicit conversion
testyall.bas(15) : warning level 0: Suspicious Pointer assignment
testyall.bas(15) : Error 30: Expected Pointer, before: '->'

    DefineListType(String)
                          ^
testyall.bas(15) : Error 120: Too many errors, exiting

C:\FreeBASIC\FB_17>


Last edited by gedumer on Oct 25, 2006 0:24; edited 1 time in total
 
Back to top
View user's profile
krcko

PostPosted: Oct 19, 2006 22:13    Post subject: Reply with quote

you must have latest version from CVS... if you have it then i dunno why you're getting errors (i'm not)...

what's the code in testyall.bas?
 
Back to top
View user's profile Send e-mail Visit poster's website MSN Messenger
gedumer

PostPosted: Oct 19, 2006 22:26    Post subject: Reply with quote

I just copied your code from YALL above. I didn't download the CVS. I used whatever Victor has on the site for Windows (17b I think).
 
Back to top
View user's profile
gedumer

PostPosted: Oct 19, 2006 22:34    Post subject: Reply with quote

BTW... it works with JALL but not with YALL.
 
Back to top
View user's profile
gedumer

PostPosted: Oct 20, 2006 1:11    Post subject: Reply with quote

OK... I downloaded Pritchard's latest CVS build and it's works fine.
 
Back to top
View user's profile
gedumer

PostPosted: Oct 20, 2006 2:12    Post subject: Reply with quote

I added the JALL test program to the YALL test program and it works fine.

I'd like to see the following function/sub's added:


    GetFirst() - first in list
    GetLast() - last in list
    Find(value)
    GetNext() - from the current record pointer
    GetPrior() - from the current record pointer
    Insert(index)
    PopFirst - instead of Pop
    PopLast - instead of PopBack
 
Back to top
View user's profile
krcko

PostPosted: Oct 20, 2006 21:13    Post subject: Reply with quote

ok, i've changed it a bit..

Macros:
DefineListType(Type)
- defines new list type

DefineDynamicListType(Type)
- same as DefineListType but when .Set is called, data pointer is reallocated.
this should be used with dynamic length types (strings)


Properties:
Count As Integer
- returns length of list (number of items)

Position As Integer
- returns current position


Methods:
Add(ByRef Item As <type>)
- adds item to the end of list

Remove(ByRef Index As Integer)
- removes item at Index position

GetItem(Index As Integer) As <type>
- returns item from Index position

Set(Index As Integer, ByRef Item As <type>)
- changes value of item at Index position

Push(ByRef Item As <type>)
- adds item to the top of list

Pop() As <type>
- returns value of the item from the top of the list, and removes it

PopFirst() As <type>
- alias of Pop

PopLast() As <type>
- returns value of the item from the bottom of the list, and removes it

Clear()
- removes all items from the list

Resize(Value As Integer)
- resizes list (expands or truncates list)

Current() As <type>
- returns item at current position

MoveNext()
- moves to the next item in the list (incerments current position)

MovePrevious()
- moves to the previous item in the list (decrements current position)

MoveFirst()
- moves to the first item in the list (sets current position to 1)

MoveLast()
- moves to the last item in the list (sets current position to .Count)

EOF() As Byte
- returns 1 if current position is out of bounds (0 otherwise)

Insert(ByRef Item As <type>, Index As Integer = 0)
- inserts new item at Index position, if Index is not specified, value is inserted at current position

"yall.bas"
Code:

'
' -------------------------------------------------------------------------
'
'   YALL - Yet Another Linked List
'
'   by Aleksandar Ruzicic (admin@krcko.net)
'
'   Feel free to use this if you like it, just:
'   "give credit where credit is due" :)
'
' -------------------------------------------------------------------------

# ifndef __YALL_BAS__
   
#   Define __YALL_BAS__
   
#   macro DefineListType( __TYPE__ )
       
#       ifndef __YALL__LIST__TYPE__##__TYPE__##__DEFINED__
           
#           Define __YALL__LIST__TYPE__##__TYPE__##__DEFINED__
           
            Type __TYPE__##ListItem
               
                p_data  As __TYPE__ Pointer
                p_next  As __TYPE__##ListItem Pointer
                p_prev  As __TYPE__##ListItem Pointer
                   
            End Type
           
            Type __TYPE__##List
               
                p_first As __TYPE__##ListItem Pointer
                p_last  As __TYPE__##ListItem Pointer
                p_cur   As __TYPE__##ListItem Pointer
               
                Count       As Integer
                Position    As Integer
               
                Declare Sub Add(Byref Item As __TYPE__)
                Declare Sub Remove(ByRef Index As Integer)
                Declare Function GetItem(Index As Integer) As __TYPE__
                Declare Sub Set(Index As Integer, Byref Item As __TYPE__)
                Declare Sub Push(Byref Item As __TYPE__)
                Declare Function Pop() As __TYPE__
                Declare Function PopFirst() As __TYPE__
                Declare Function PopLast() As __TYPE__
                Declare Sub Clear()
                Declare Sub Resize(Value As Integer)
                Declare Function Current() As __TYPE__
                Declare Sub MoveNext()
                Declare Sub MovePrevious()
                Declare Sub MoveFirst()
                Declare Sub MoveLast()
                Declare Function Eof() As Byte
                Declare Sub Insert(Byref Item As __TYPE__, Index As Integer = 0)
               
                Declare Destructor()
               
            End Type
           
            Sub __TYPE__##List.Add(Byref newItem As __TYPE__)
               
                Dim tmp As __TYPE__##ListItem Pointer
               
                tmp = Callocate(Len(__TYPE__##ListItem))
               
                tmp->p_data = Callocate(Len(newItem))
                *tmp->p_data = newItem
               
                This.Count += 1
               
                If This.p_first = 0 Then
                   
                    This.p_first = tmp
                    This.p_last = tmp
                    This.p_cur = tmp
                   
                Else
                   
                    tmp->p_prev = This.p_last
                    This.p_last->p_next = tmp                   
                    This.p_last = tmp

                End If                 
               
            End Sub
           
            Sub __TYPE__##List.Remove(ByRef Index As Integer)
               
                If Index > 0 And Index <= This.Count Then
                   
                    Dim As __TYPE__##ListItem Pointer item = This.p_first, nextItem, prevItem
                    Dim i As Integer
                   
                    For i = 1 To Index - 1
                        item = item->p_next
                    Next
                   
                    nextItem = item->p_next
                    prevItem = item->p_prev
                   
                    If nextItem <> 0 Then nextItem->p_prev = prevItem
                    If prevItem <> 0 Then prevItem->p_next = nextItem
                   
                    If This.p_first = item Then This.p_first = nextItem
                    If This.p_last = item Then This.p_last = prevItem
                   
                    Deallocate(item->p_data)
                    Deallocate(item)
                   
                    This.Count -= 1
                   
                End If
               
            End Sub
           
            Function __TYPE__##List.GetItem(Index As Integer) As __TYPE__
               
                If Index > 0 And Index <= This.Count Then
                   
                    Dim As __TYPE__##ListItem Pointer item = This.p_first
                    Dim i As Integer
                   
                    For i = 1 To Index - 1
                        item = item->p_next
                    Next
                   
                    Return *item->p_data
                       
                End If
               
               
            End Function
           
            Sub __TYPE__##List.Set(Index As Integer, Byref Item As __TYPE__)
               
                If Index > 0 And Index <= This.Count Then
                   
                    Dim As __TYPE__##ListItem Pointer tmp = This.p_first
                    Dim i As Integer
                   
                    For i = 1 To Index - 1
                        tmp = tmp->p_next
                    Next
                   
#                   ifdef __YALL__LIST__TYPE__##__TYPE__##__DYNAMIC__
                    tmp->p_data = Reallocate(tmp->p_data, Len(Item))
#                   Endif

                    *tmp->p_data = Item
                   
                End If
               
            End Sub
           
            Sub __TYPE__##List.Push(Byref Item As __TYPE__)
               
                Dim As __TYPE__##ListItem Pointer tmp, nextItem
               
                This.Count += 1
               
                tmp = Callocate(Len(__TYPE__##ListItem))
               
                tmp->p_data = Callocate(Len(__TYPE__))
                *tmp->p_data = Item
               
                nextItem = This.p_first
               
                This.p_first = tmp
               
                If nextItem <> 0 Then
                   
                    nextItem->p_prev = tmp
                    This.p_first->p_next = nextItem
               
                Else
                   
                    This.p_last = tmp
                   
                End If
               
            End Sub
           
            Function __TYPE__##List.Pop() As __TYPE__
               
                If This.Count > 0 Then
                   
                    Dim As __TYPE__ Result
                    Dim As __TYPE__##ListItem Pointer nextItem
                   
                    Result = *This.p_first->p_data
                   
                    nextItem = This.p_first->p_next
                   
                    Deallocate(This.p_first->p_data)
                    Deallocate(This.p_first)
                   
                    This.p_first = nextItem
                    This.p_first->p_prev = 0
                   
                    This.Count -= 1
                   
                    Return Result
                   
                End If
           
            End Function
           
            Function __TYPE__##List.PopFirst() As __TYPE__
               
                Return This.Pop
               
            End Function
           
            Function __TYPE__##List.PopLast() As __TYPE__
               
                If This.Count > 0 Then
                   
                    Dim As __TYPE__ Result
                    Dim As __TYPE__##ListItem Pointer prev
                   
                    Result = *This.p_last->p_data
                   
                    prev = This.p_last->p_prev
                   
                    Deallocate(This.p_last->p_data)
                    Deallocate(This.p_last)
                   
                    This.p_last = prev
                    This.p_last->p_next = 0
                   
                    This.Count -= 1
                   
                    Return Result
                   
                End If
           
            End Function
           
            Sub __TYPE__##List.Clear()
               
                If This.Count > 0 Then
                   
                    Dim As __TYPE__##ListItem Pointer item1, item2
                   
                    item1 = This.p_first
                   
                    While item1 <> 0
                       
                        item2 = item1
                        item1 = item1->p_next
                       
                        Deallocate(item2->p_data)
                        Deallocate(item2)
                       
                    Wend
                   
                    This.Count = 0
                   
                End If
               
            End Sub
           
            Sub __TYPE__##List.Resize(Value As Integer)
               
                If Value < 1 Then
                    This.Clear
                Else
                    Dim dummy As __TYPE__
                    Dim i As Integer
                   
                    If Value < This.Count Then
               
                        For i = Value To This.Count - 1
                           
                            dummy = This.PopLast
                           
                        Next
                       
                    Else               
                       
                        Dim As Integer from = This.Count
                       
                        For i = from To Value - 1
                           
                            This.Add(dummy)
                           
                        Next
                       
                    End If
                   
                End If
               
            End Sub
           
            Function __TYPE__##List.Current() As __TYPE__
               
                If This.p_cur <> 0 Then
                   
                    If This.p_cur->p_data <> 0 Then Return *This.p_cur->p_data
                   
                End If
           
            End Function
           
            Sub __TYPE__##List.MoveNext()
               
                If This.p_cur <> 0 Then
                   
                    This.p_cur = This.p_cur->p_next
                   
                    This.Position += 1
               
                End If
           
            End Sub
           
            Sub __TYPE__##List.MovePrevious()
               
                If This.p_cur <> 0 Then
                   
                    This.p_cur = This.p_cur->p_prev
                   
                    This.Position -= 1
               
                End If
           
            End Sub
           
            Sub __TYPE__##List.MoveFirst()
               
                This.p_cur = This.p_first
               
                This.Position = 1
               
            End Sub
           
            Sub __TYPE__##List.MoveLast()
               
                This.p_cur = This.p_last
               
                This.Position = This.Count
           
            End Sub
           
            Function __TYPE__##List.EOF() As Byte
               
                If This.p_cur <> 0 Then Return 0
               
                Return 1
                   
            End Function
           
            Sub __TYPE__##List.Insert(Byref Item As __TYPE__, Index As Integer = 0)
               
                Dim As __TYPE__##ListItem Pointer nextItem, prevItem, newItem
               
                If Index > 0 Then
                   
                    If Index > This.Count Then Return
                       
                    Dim i As Integer
               
                    nextItem = This.p_first
               
                    For i = 1 To Index - 1
                        nextItem = nextItem->p_next
                    Next
                   
                Elseif This.p_cur <> 0 Then
                   
                    nextItem = This.p_cur
                    Index = This.Position
                   
                Else
                    Return
                End If
               
                prevItem = nextItem->p_prev
               
                newItem = Allocate(Len(__TYPE__##ListItem))
               
                newItem->p_data = Allocate(Len(Item))
                *newItem->p_data = Item
               
                If prevItem <> 0 Then prevItem->p_next = newItem
               
                newItem->p_prev = prevItem
                newItem->p_next = nextItem
               
                nextItem->p_prev = newItem
               
                If Index = 1 Then This.p_first = newItem
                If Index = This.Count Then This.p_last = nextItem
               
                This.Count += 1
               
            End Sub
           
            Destructor __TYPE__##List()
               
                This.Clear
           
            End Destructor
           
#       Endif
       
#   endmacro


#   macro DefineDynamicListType( __TYPE__ )

#       Define __YALL__LIST__TYPE__##__TYPE__##__DYNAMIC__

        DefineListType(__TYPE__)

#   endmacro

# Endif
 



Tip: the .MoveFirst/While/.Current/.MoveNext combination is faster then For/.GetItem

i mean, this:
Code:

list.MoveFirst
While list.EOF = 0
  Print list.Position; ": "; list.Current
  list.MoveNext
Wend
 

is faster then
Code:

For i = 1 To list.Count
  Print i; ": "; list.GetItem(i)
Next
 


Last edited by krcko on Oct 21, 2006 23:05; edited 1 time in total
 
Back to top
View user's profile Send e-mail Visit poster's website MSN Messenger
gedumer

PostPosted: Oct 21, 2006 0:25    Post subject: Reply with quote

Wow... I love the new functions... Thanks!

I tried to test the combined JALL/YALL program and it bombs at line 137. Right after the Print "***BOMBS HERE***" statement below:

Code:

   
    #include "yall.bi"

   
    Type UDT
        i   As Integer
        d   As Double
    End Type
   
    Dim i As Integer ' counter in loops
    Dim j As Integer ' counter in loops
    Dim u As UDT ' used in debugUDT macro
   
    #Macro debugList(__lst__)
       
        Print #__lst__; " items:"
       
        For i = 1 To __lst__.Count
       
            Print i; ": "; __lst__.GetItem(i)
       
        Next
       
        Print ""
       
    #EndMacro
   
    #Macro debugUDT(__lst__)
       
        Print #__lst__; " items:"
       
        For i = 1 To __lst__.Count
           
            u = __lst__.GetItem(i)
           
            Print i; ": "; u.i; ", "; u.d
           
        Next
       
        Print ""
       
    #EndMacro
   
    DefineListType(Integer) ' define IntegerList
    DefineListType(String)  ' define StringList
'    DefineDynamicListType(String) ' define Dynamic StringList
    DefineListType(UDT)     ' define UDTList

    ' declare lists
    Dim list1 As IntegerList
    Dim list2 As StringList
    Dim list3 As UDTList
    Dim test  As StringList

    ' declare some variables
    Dim v1 As Integer
    Dim v2 As String
    Dim v3 As UDT
   
    ''' integer list '''
   
    ' adding integers to list1
    For i = 0 To 19
        List1.Add(i)
    Next
   
    debugList(list1)
   
    ' clear list1
    List1.Clear()
   
    v1 = 42
   
    ' push some data into list1
    List1.Push(1)
    List1.Push(10)
    List1.Push(v1)
    List1.Push(88)
   
    debugList(list1)
   
    v1 = 18 ' change variable's value
   
    debugList(list1) ' nothing changed!
   
    ' change value of list item with index 2
    List1.Set(2, 18)

    debugList(list1)
   
    ' remove item with index 3
    List1.Remove(3)
   
    debugList(list1)
   
    ' pop value
    Print "popped: "; List1.PopFirst()
    Print
   
    debugList(list1)
   
   
    ''' string list '''

    ' fill list2 with some values:
    v2 = "blah"
   
    List2.Push("foo")
    List2.Push(v2)
    List2.Push("bar")
   
    debugList(list2)

    v2 = "this is changed"
   
    debugList(list2)
   
    List2.Set(2, v2)

    debugList(list2)
   
    While (i <= list2.count)

        Print "popped: "; List2.PopFirst()

    Wend

    Print
   
    List2.Add("item1")
    List2.Add("item2")
    List2.Add("item3")
   
    debugList(list2)
Print "***BOMBS HERE***"
    List2.Add("added")
    List2.Push("pushed")

    debugList(list2)

   
    ''' udt list '''
   
    List3.Add(Type<UDT>(1, 0.5))
    List3.Add(Type<UDT>(0, 3.14))
    List3.Add(Type<UDT>(123, 48.58565))
    List3.Add(Type<UDT>(448, 45680.5654))

    debugUDT(list3)

    v3.i = 20
    v3.d = 5.6987

    List3.Push(v3)

    debugUDT(list3)
   
    v3.i = 345

    debugUDT(list3)
   
    List3.Set(1, Type<UDT>(345, 5.6987))

    debugUDT(list3)

    ''' Test another string '''

    test.push "foo"
    test.push "blah blah blah"
    test.push "bar"
   
    debugList(test)

    test.push "pushed"
    test.add "added"
   
    debugList(test)
   
    Print "popped: "; test.popfirst
    Print
    Print "back-popped: "; test.poplast
    Print

    debugList(test)
   
    test.Remove 2

    debugList(test)

    test.set 1, "foo"
    test.set 2, "bar"

    debugList(test)
   
    test.clear

    Sleep
 


I tried defining list2 using DefineListType(String) and DefineDynamicListType(String) and got the same results.

BTW... did you consider a Find(value) function?


Last edited by gedumer on Oct 21, 2006 2:08; edited 1 time in total
 
Back to top
View user's profile
gedumer

PostPosted: Oct 21, 2006 1:51    Post subject: Reply with quote

Position and p_cur need to be updated every time an add or delete action takes place. ADD, PUSH, INSERT, REMOVE, POPFIRST, POPLAST must all set POSITION and P_CUR. I think the only time you set p_cur in the ADD function is when it's the first record. They also must be updated when movement actions take place... I think you're already doing that.
 
Back to top
View user's profile
gedumer

PostPosted: Oct 21, 2006 2:05    Post subject: Reply with quote

I just realized something, you can't go to a specific position (ie. Index). I think you need a GotoItem(index) function. Do you agree?
 
Back to top
View user's profile
Display posts from previous:   
Post new topic   Reply to topic    freebasic.net Forum Index -> Tips and Tricks All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum



sf.net phatcode