Results 1 to 21 of 21

Thread: most appropriate data structure

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 1999
    Location
    New Jersey
    Posts
    334

    most appropriate data structure

    Hi all,
    I am currently writing a completely object oriented graphical application. I have a certain type of object that at some points in the program will not exist at all, but at other points there ay be numerous instances of this object.

    I want some sort of data structure to hold all of the objects of this type, so that I can easily perform actions on all of them. I'm thinking something along the lines of a stack or queue (from Java), as I will be adding and taking away from this list of objects frequently.

    As my VB is a bit rusty (and never was too great anyway), I wanted to do this with a dynamic array, but this certainly doesnt seem like the best option due to arrays' limitations. Are there any other structures I can use, or a way I can manipulate dynamic arrays to model the behaviour I need?

    Thanks a lot!

  2. #2
    Frenzied Member David.Poundall's Avatar
    Join Date
    Sep 2002
    Location
    Robin Hood Land
    Posts
    1,457

    Re: most appropriate data structure

    What do you consider a limitation of the Array aproach?
    David

    Learn the Rules so that you know how to break them properly.

    Printing dll dBTools MZTools Winsock API WinsockVB More Winsock SGrid2 MSChart Mail2Web

    If you have found this thread useful then read this

  3. #3
    PowerPoster
    Join Date
    Oct 2002
    Location
    British Columbia
    Posts
    9,758

    Re: most appropriate data structure

    Look into the Collection object.

  4. #4

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 1999
    Location
    New Jersey
    Posts
    334

    Re: most appropriate data structure

    Ill look into Collections, thanks.

    As to the limitations of the array approach:
    As far as I know, though I can declare a dynamic array without any initial items, and then redimming it to add more data to it. However, if I want to get get rid of all data, as far as I know I have to keep one item, thereby taking up unwanted space in memory. Also, from my experience, it is hard to efficiently add and remove items from the array (not just fom the end, but from the middle as well) without wasting system resources.

    Please correct me if Im wrong, however.

  5. #5
    Banned dglienna's Avatar
    Join Date
    Jun 2004
    Location
    Center of it all
    Posts
    17,901

    Re: most appropriate data structure

    you can redim array(0)

  6. #6

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 1999
    Location
    New Jersey
    Posts
    334

    Re: most appropriate data structure

    Quote Originally Posted by dglienna
    you can redim array(0)
    Which will leave it with one element, will it not?

  7. #7
    Hyperactive Member Disiance's Avatar
    Join Date
    Sep 2004
    Location
    Denver, CO
    Posts
    439

    Re: most appropriate data structure

    yes, but just replace the '0' with another number.
    "I don't want to live alone until I'm married" - M.M.R.P

  8. #8
    Banned dglienna's Avatar
    Join Date
    Jun 2004
    Location
    Center of it all
    Posts
    17,901

    Re: most appropriate data structure

    I wouldn't worry about single value array memory consumption, but if its that important, than you could look into a collection. I don't know if you can have zero collection objects, as the definition takes up memory.

  9. #9
    PowerPoster
    Join Date
    Oct 2002
    Location
    British Columbia
    Posts
    9,758

    Re: most appropriate data structure

    The Erase statement will remove a dynamic array from memory, no need to use Redim(0).

    How important is speed? A collection adds overhead, both in memory consumption and speed (although neglible). Do you need "Game" type speed, where everything must complete in say 30ms or "User" speed where processing in 1000ms is hardly noticable.

  10. #10
    Banned dglienna's Avatar
    Join Date
    Jun 2004
    Location
    Center of it all
    Posts
    17,901

    Re: most appropriate data structure

    if you erase it, do you need to use DIM again, or can you use REDIM for it?

  11. #11
    Frenzied Member David.Poundall's Avatar
    Join Date
    Sep 2002
    Location
    Robin Hood Land
    Posts
    1,457

    Re: most appropriate data structure

    I agree on the overjhead bit. I have found in the past that collections were slower by a factor of 4 or 5 to use than arrays. I use them as a last resort or if I need to index an array.

    Another factor against using collections is that you cannot hover over them at debug time to get the value associated with the collection. With arrays you can. Thats probably a mute point as spandex is dealing with objects.

    My final gripe on collections (now where did I leave that soap box ) is that they are picky about having duplicate key names and a right pain to delete from.

    Hmmm - having said all that, given a FIFO or a stack requirement, so long as you don't use keys and you are only using the collection as a container to hold items that you are going to cycle through and process, collections should be the best aproach.
    David

    Learn the Rules so that you know how to break them properly.

    Printing dll dBTools MZTools Winsock API WinsockVB More Winsock SGrid2 MSChart Mail2Web

    If you have found this thread useful then read this

  12. #12

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 1999
    Location
    New Jersey
    Posts
    334

    Re: most appropriate data structure

    Quote Originally Posted by brucevde
    The Erase statement will remove a dynamic array from memory, no need to use Redim(0).

    How important is speed? A collection adds overhead, both in memory consumption and speed (although neglible). Do you need "Game" type speed, where everything must complete in say 30ms or "User" speed where processing in 1000ms is hardly noticable.
    I need "game " type speed, that's the onl reason that this is even a consideration. I can tell that this is my first time attempting to do "efficient" programming, as I normally dont pay attention to speed issues.

    I'm having troubles understanding, however, how to use an array to act the same as a collection. For instance, how do we go about deleting just one element somewhere in the array and "dynamically" adjusting the size of the array to account for this? Same goes for changing the order of elements...

  13. #13
    Frenzied Member David.Poundall's Avatar
    Join Date
    Sep 2002
    Location
    Robin Hood Land
    Posts
    1,457

    Re: most appropriate data structure

    If I were doing this I would have a 2D array, set to say 100 items.

    (0,x) would hold the object, (1,x) would hold status info for the object. You could record status as destroyed, active, needs to be checked etc.

    I would then cycle around all of the status array entries and operate on the objects as needed. If you have more than 100 objects on the go then you could extend the array with redim preserve array(0 to 1, 0 to ubound(array)+50) say or you could re-use "Destroyed" locations in the original array.

    There is no destroying or rebuilding of arrays, the pointer contol is clean and fast.
    David

    Learn the Rules so that you know how to break them properly.

    Printing dll dBTools MZTools Winsock API WinsockVB More Winsock SGrid2 MSChart Mail2Web

    If you have found this thread useful then read this

  14. #14

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 1999
    Location
    New Jersey
    Posts
    334

    Re: most appropriate data structure

    Quote Originally Posted by David.Poundall
    If I were doing this I would have a 2D array, set to say 100 items.

    (0,x) would hold the object, (1,x) would hold status info for the object. You could record status as destroyed, active, needs to be checked etc.

    I would then cycle around all of the status array entries and operate on the objects as needed. If you have more than 100 objects on the go then you could extend the array with redim preserve array(0 to 1, 0 to ubound(array)+50) say or you could re-use "Destroyed" locations in the original array.

    There is no destroying or rebuilding of arrays, the pointer contol is clean and fast.
    THat's an interesting approach, thanks. I'll give something like that a go.

  15. #15
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359

    Re: most appropriate data structure

    2 comments.

    1) Redim without the Preserve keyword will clear the contents of the array
    2) Erase will delete the array
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  16. #16
    Fanatic Member VBAhack's Avatar
    Join Date
    Dec 2004
    Location
    Sector 000
    Posts
    617

    Re: most appropriate data structure

    You can use the memory managment API's for stacks and queues. Here is a simple example

    Code:
    Private Declare Sub CopyMemoryPut Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As Long, Source As Any, ByVal Length As Long)
    Private Declare Sub CopyMemoryRead Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, ByVal Source As Long, ByVal Length As Long)
    
    Private Type Node
        Data As Long
        Next As Long
    End Type
    
    Dim cNode as Node, i as long, pCurrent as long
    pCurrent = HeapAlloc(hHeap, 0, 8) 
    For i = 1 To 10
       cNode.Data = i
       cNode.Next = HeapAlloc(hHeap, 8, 8) 
       CopyMemoryPut pCurrent, cNode, 8
       pCurrent = cNode.Next
    Next i

  17. #17
    Former Admin/Moderator MartinLiss's Avatar
    Join Date
    Sep 1999
    Location
    San Jose, CA
    Posts
    33,431

    Re: most appropriate data structure

    Quote Originally Posted by brucevde
    The Erase statement will remove a dynamic array from memory, no need to use Redim(0).

    How important is speed? A collection adds overhead, both in memory consumption and speed (although neglible). Do you need "Game" type speed, where everything must complete in say 30ms or "User" speed where processing in 1000ms is hardly noticable.
    Some times a collection is a lot faster than an array.

    VB Code:
    1. Option Explicit
    2. Private Declare Function GetTickCount Lib "kernel32" () As Long
    3.  
    4. Private Sub Form_Load()
    5.     ' Place this code in any Sub or Function
    6.     Dim lngStart As Long
    7.     Dim lngFinish As Long
    8.     Dim lngCounter As Long
    9.    
    10.     ' Record the start "time"
    11.     lngStart = GetTickCount()
    12.    
    13.     ' About 60ms on my PC
    14. '    Dim MyCollection As New Collection
    15. '    For lngCounter = 1 To 100000
    16. '        MyCollection.Add lngCounter
    17. '    Next
    18.    
    19.     ' About 5200ms on my PC
    20.     Dim MyArray() As Long
    21.     For lngCounter = 1 To 100000
    22.         ReDim MyArray(lngCounter)
    23.         MyArray(lngCounter) = lngCounter
    24.     Next
    25.    
    26.    
    27.     ' Record the finish "time"
    28.     lngFinish = GetTickCount()
    29.    
    30.     ' Display the difference
    31.     MsgBox CStr(lngFinish - lngStart)
    32. End Sub

  18. #18
    Former Admin/Moderator MartinLiss's Avatar
    Join Date
    Sep 1999
    Location
    San Jose, CA
    Posts
    33,431

    Re: most appropriate data structure

    BTW, this takes 15ms but there's probably a lot of wasted space.

    VB Code:
    1. Dim MyArray(100000) As Long
    2.     For lngCounter = 1 To 100000
    3.         'ReDim MyArray(lngCounter)
    4.         MyArray(lngCounter) = lngCounter
    5.     Next

  19. #19
    Fanatic Member VBAhack's Avatar
    Join Date
    Dec 2004
    Location
    Sector 000
    Posts
    617

    Re: most appropriate data structure

    Some times a collection is a lot faster than an array.
    In your example yes, but my experience with collections is that they are extremely slow when you include reading and deleting items. Also, executing the redim preserve statement on every iteration is what really slows down the array example. Arrays are extremely fast.

    BTW, this takes 15ms but there's probably a lot of wasted space.

    visual basic code:------ Dim MyArray(100000) As Long
    For lngCounter = 1 To 100000
    'ReDim MyArray(lngCounter)
    MyArray(lngCounter) = lngCounter
    Next
    Right you are on both counts!. But, the following executes in the same abount of time (10-20 ms) AND and memory can easily be de-allocated item by item.

    VB Code:
    1. hHeap = GetProcessHeap()
    2.     pCurrent = HeapAlloc(hHeap, 0, 8)
    3.     For i = 1 To 10000
    4.         cNode.Data = i
    5.         cNode.Next = HeapAlloc(hHeap, 8, 8)
    6.         CopyMemoryPut pCurrent, cNode, 8
    7.         pCurrent = cNode.Next
    8.     Next i

  20. #20
    Fanatic Member VBAhack's Avatar
    Join Date
    Dec 2004
    Location
    Sector 000
    Posts
    617

    Re: most appropriate data structure

    Ooops, off by a factor of 10. The API example I just posted takes about 150ms (10x the array example). Thus, if you want raw speed, arrays can't be beat. But if you want an elegant C-like data structure, the memory API's seem like a good choice.

    VBAhack

  21. #21
    Fanatic Member VBAhack's Avatar
    Join Date
    Dec 2004
    Location
    Sector 000
    Posts
    617

    Re: most appropriate data structure

    I remember doing performance comparisions long ago and just had to do it again to confince myself. Yep, the Collection is very slow at retrieving/removing objects. See code example comparing Collection, Linked-List based on memory API, and array. The array is, of course, the hands down winner, but the example isn't exactly fair because you can't delete array items one by one. Just for kicks I commented out the Collection remove line and there wasn't much difference.

    VBAhack

    VB Code:
    1. Option Explicit
    2.  
    3. Private Declare Function HeapAlloc Lib "kernel32" (ByVal hHeap As Long, ByVal dwFlags As Long, ByVal dwBytes As Long) As Long
    4. Private Declare Function GetProcessHeap Lib "kernel32" () As Long
    5. Private Declare Function GetTickCount Lib "kernel32" () As Long
    6. Private Declare Sub CopyMemoryPut Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As Long, Source As Any, ByVal Length As Long)
    7. Private Declare Sub CopyMemoryRead Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, ByVal Source As Long, ByVal Length As Long)
    8. Private Declare Function HeapFree Lib "kernel32" (ByVal hHeap As Long, ByVal dwFlags As Long, lpMem As Any) As Long
    9.  
    10. Private Type Node
    11.     Data As Long
    12.     Next As Long
    13. End Type
    14.  
    15. Private Sub Form_Load()
    16.     ' Place this code in any Sub or Function
    17.     Dim lngStart As Long, lngFinish As Long, lngCounter As Long, lngItems As Long, lngData As Long
    18.     Dim lngCnt1 As Long, lngCnt2 As Long, lngCnt3 As Long, lngCnt4 As Long, lngCnt5 As Long
    19.     Dim cNode As Node, i As Long, pCurrent As Long, hHeap As Long, pStart As Long
    20.     lngItems = 30000
    21.     lngStart = GetTickCount() ' Record the start time
    22.    
    23.     ' Collection (fast to create, but slow to retrieve/delete)
    24.     Dim MyCollection As New Collection
    25.     For lngCounter = 1 To lngItems
    26.         MyCollection.Add lngCounter
    27.     Next
    28.     lngCnt1 = GetTickCount()
    29.     For lngCounter = lngItems To 1 Step -1
    30.         lngData = MyCollection.Item(lngCounter)
    31.         MyCollection.Remove (lngCounter)
    32.     Next
    33.     lngCnt2 = GetTickCount()
    34.    
    35.     ' Memory API linked-list
    36.     hHeap = GetProcessHeap()
    37.     pStart = HeapAlloc(hHeap, 0, 8)
    38.     pCurrent = pStart
    39.     For lngCounter = 1 To lngItems
    40.         cNode.Data = lngCounter
    41.         cNode.Next = HeapAlloc(hHeap, 8, 8)
    42.         CopyMemoryPut pCurrent, cNode, 8
    43.         pCurrent = cNode.Next
    44.     Next
    45.     lngCnt3 = GetTickCount()
    46.     pCurrent = pStart
    47.     For lngCounter = 1 To lngItems
    48.         CopyMemoryRead cNode, pCurrent, 8
    49.         HeapFree GetProcessHeap(), 0, pCurrent
    50.         pCurrent = cNode.Next
    51.         lngData = cNode.Data
    52.     Next
    53.     lngCnt4 = GetTickCount()
    54.    
    55.     ' Array
    56.     ReDim MyArray(lngItems) As Long
    57.     For lngCounter = 1 To lngItems
    58.         MyArray(lngCounter) = lngCounter
    59.     Next
    60.     lngCnt5 = GetTickCount()
    61.     For lngCounter = 1 To lngItems
    62.         lngData = MyArray(lngCounter)
    63.     Next
    64.     Erase MyArray
    65.     lngFinish = GetTickCount() ' Record the finish "time"
    66.    
    67.     ' Display the difference
    68.     ' 30000 item Collection: Create = 50  Create, Touch & Remove = 24144
    69.     ' 30000 item API l-list: Create = 40  Create, Touch & Remove = 60
    70.     ' 30000 item      Array: Create = 10  Create, Touch & Remove = 10
    71.     Debug.Print lngItems & " item Collection: Create = " & lngCnt1 - lngStart & _
    72.     "  Create, Touch & Remove = " & lngCnt2 - lngStart
    73.    
    74.     Debug.Print lngItems & " item API l-list: Create = " & lngCnt3 - lngCnt2 & _
    75.     "  Create, Touch & Remove = " & lngCnt4 - lngCnt2
    76.    
    77.     Debug.Print lngItems & " item      Array: Create = " & lngCnt5 - lngCnt4 & _
    78.     "  Create, Touch & Remove = " & lngFinish - lngCnt4
    79. End Sub

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width