I was looking in Generics.Collections and noticed there was no linked list. Sure they are simple to make, but I thought it was odd there was not one (or I just missed it). Are linked lists just outdated when compared to new modern data structures, or is there a need for a general generic linked list? Does anyone know of one?
Do you know the DeHL?
I think the TLinkedList<T> from the DeHL.Collections.LinkedList.pas unit is exactly what you are looking for.
In the old days, almost any piece of serious software contained linked lists or trees.
I haven't used linked lists alot, but trees are another story.
With the introduction of dynamic arrays, there is not that much need for linked lists. But I can imagine that you want to use it if your datastructure is changed often (add + delete).
You can easily create a generic linked list yourself, using a container class and records for the elements.
I don't know of any generic, linked list in the existing Delphi RTL.
They are still very useful as a data structure, however. Especially if you include variants on a linked list such as a b-tree or a binary tree. Unlike a regular list, a linked list can be expanded, edited, or modified without moving data in memory. They are very easy to version, and work well in purely functional code which does not allow mutating existing data. So it is still a very useful data structure.
Isn't that what tStringList is for?
(ducking)
Actually, any generic tList works fine as a linked list, and supplies most of the functionality needed. The ancient technique passed down from our ancestors of storing a pointer to memory in each record, and navigating to that has been easily replaced by dynamic arrays and doing things...more generically.
Related
I'm seeing a lot of solutions to these Leetcode LinkedList problems involve creating a dummy node, e.g.
Example
It seems to me that constructing this one additional ListNode object isn't a big deal and more importantly, considerably simplifies code. However, in my school, creating this kind of additional object is SEVERELY penalized.
I'm just wondering, is creating this extra dummy node acceptable in actual industry work? It makes code a lot more concise, yet is technically using extra resources
is creating this extra dummy node acceptable in actual industry work?
Yes. Although there aren't that many examples I can think of where you would use linked lists in production code and would have to implement the linked list data structure yourself (as opposed to using an implementation provided by the programming language or a standard library that comes with it).
It makes code a lot more concise
Yes
...yet is technically using extra resources.
Yes, but not more than when you would use two additional variables in your code. So this is not really an issue. A dummy node represents O(1) auxiliary space, which is what you would use anyway for iterating through a linked list using a node pointer/reference.
in my school, creating this kind of additional object is SEVERELY penalized.
Too bad.
I'm trying to understand Streams.
How comparable is a stream (computer science) with a stream (water). This is how I picture them in my mind:
Now, I was wondering whether this thought is correct. If it's not a correct way, why isn't this a correct way?
In information science, there is a specific meaning attached to the notation of two adjacent boxes, one with a value and another with an arrow pointing to another box pair. It stands for a node of a singly-linked list (or just "linked list".) This is an object which contains a value (otherwise known as payload) and a pointer to the next node of the list.
Linked lists have very little in common with streams. True, both linked lists and streams are structures that can only be traversed sequentially, but the similarities end there. Linked lists are not implemented as streams, and although in theory a stream may be implemented as a linked list, it would be inefficient, so it is usually not done this way. When reading from a stream you can at any time only see the payload of the item that you have just read, you have no notion of a pointer to another item, and you cannot rearrange items by manipulating pointers.
So, no, this is not a correct way of picturing a stream in information science.
Generally, real-world metaphors are not useful at all for understanding information science entities. You need to understand the definition of the entity exclusively in information science terms, and once you have achieved this, then you can use a real-world metaphor as a name for it, nothing more.
Take for example a "file". Before computers, a file was a folder made of manila paper, containing papers. With the advent of computers, a file is an array of bytes stored on the disk, representing data or code or both, following a format which may or may not be known, and which may be standard or it may only be interpretable by specialized software. Knowing the old meaning of the word "file" does not help you at all in figuring out what a file is for computers. We just use the word "file" for convenience. We might even imagine a manila folder in our mind. But it is just a visual mnemonic, bearing no relation to reality.
I've been looking into this on Google and read the Collections entry in the SDK documentation, and turned up nothing. Is there a BST (any of its variants) implementation available out of the box with the iOS SDK?
It seems odd that something so basic would be missing from a major development platform. Is their hash implementation just that magical? Or do the devs assume no one is going to do inserts/deletes on things that have an order?
I can use NSSet for now, as I know most of us (myself included) aren't really writing anything with tons of computation on iOS that need a guaranteed access time, but it's still gnawing at me.
CFBinaryHeap looks pretty promising and useful, but it might not be exactly what you want, as it's not really a binary search tree but a heap. They are similar, but not the same, so I feel like Core Foundation's CFTree class might be a little better. Here's a description from the CFTree class reference:
You use CFTree to create tree structures that represent hierarchical organizations of information. In such structures, each tree node has exactly one parent tree (except for the root tree, which has no parent) and can have multiple children.
If you're not comfortable with C (Core Foundation is C, not Objective-C), you can use the JKPTree library which is an Objective-C wrapper of CFTree. You can download it here.
UPDATE:
I just found another library called CHDataStructures that simplifies the creation of a wide variety of data structures. It supports the following data structures (and many other unlisted ones):
AVL Tree
Abstract Binary Search Tree
Andersson Tree
Linked List
Search Tree
Red Black Tree
Unbalanced Tree
Queue
Heap
You can download CHDataStructures here.
CoreFoundation has a CFBinaryHeap type you can use. There's no Obj-C wrapper for it, but a little C never hurt anyone.
You can use std::set from the C++ standard library, if you name your file with a .mm extension (Objective-C++ mode).
It isn't Cocoa Touch, but the GNU Objective-C collections library has a Red-Black Tree and abstract Binary Tree, as well as a bunch of other non-tree collections stuff.
Although using associative references seems to be the most widely used method to fake category variables, I can't help from thinking of it as a hack. I'm probably wrong. Thus this question. So, I know Apple uses categories for many of the framework classes, and they did so way before 3.1 (when associative references were added). Which makes me wonder, were they doing it in a different way? Are associative references used this way recommended by Apple? (any docs for sustaining this?) From the design point of view, adding storage to a category is something to avoid?
Associated Objects are not a hack, as they are provided to us as standard functions in the "modern" runtime.
You are right, Associated Objects were not implemented before the "Modern" runtime, however Apple had no use for them. If they wished to add variables to a class, it was done with a combination of an explicit setter/getter/internal iVar (you'll notice this especially with old Cocoa classes like NSSplitView) in the main class (because why would you need to use associated objects if you owned the framework?) Apple's use of categories was the old way of grouping similar functions together, something like a language level #pragma mark -.
I'm looking for a way to control all business objects I create in my applications written in Delphi.
As an article on Embarcadero's EDN (http://edn.embarcadero.com/article/28217) states, there are basically three ways to do this. I'm mostly interested in the last one, using interfaces. That way, when the business object is no longer being referenced anywhere in the application, it will be dispose of memory wise (I'll get back on this part later).
When creating a new business object, it would be wise to ask that new object manager whether I already fetched it earlier in the program, thus avoid the need to refetch it from the database. I already have the business object in memory, so why not use that one? Thus I'll need the list of available objects in memory to be searchable (fast).
The provided code there uses an "array of TObject" to store the collected objects, which doesn't make it very performant concerning searches through the list of objects once you get to a certain amount. I would have to change that to either TObjectList or some sort of binary searchable tree. What would be the best choice here? I already found some useful code (I think) at http://www.ibrtses.com/delphi/binarytree.html. Didn't JCL have stuff on binary trees?
How would I handle "business objects" and "lists of business objects" in that tree? Would a business object, being part of a list be referenced twice in the tree?
Concerning the disposing of an object: I also want to set some sort of TTL (time to life) to that business object, forcing a refetch after an certain amount of time.
Should the reference counter fall to 0, I still want to keep the object there for a certain amount of time, should the program still want it within the TTL. That means I'll need sort sort of threaded monitor looping the object list (or tree) to watch for to-be-deleted objects.
I also came across the Boehm Garbage Collector DLL (http://codecentral.embarcadero.com/Download.aspx?id=21646).
So in short, would it be wise to base my "object manager" on the source code provided in the EDN article? What kind of list would I want to store my objects in? How should I handle list of objects in my list? And should I still keep my object in memory for a while and have it dispose of by a threaded monitor?
Am I correct in my reasoning? Any suggestions, ideas or remarks before I start coding? Maybe some new ideas to incorporate into my code?
Btw, I'd be happy to share the result, for others to benefit, once some brilliant minds gave it a thought.
Thnx.
If you are using Interfaces for reference counting, and then stick those in a collection of some sort, then you will always have a reference to them. If your objective is "garbage collection" then you only need one or the other, but you can certainly use both if necessary.
What it sounds like you really want is a business object cache. For that you will want to use one of the new generic TDictionary collections. What you might want to do is have a TDictionary of TDictionary collections, one TDictionary for each of your object types. You could key your main TDictionary on an enumeration, or maybe even on the type of the object itself (I haven't tried that, but it might work.) If you are using GUIDs for your unique identifiers then you can put them all in a single TDictionary.
Implement each of your business objects with an interface. You don't need to use Smart Pointers since you are designing your business objects and can descend them from TInterfacedObject. Then only reference it by its interface, so it can be reference counted.
If you want to expire your cache then you will need to have some sort of timestamp on your objects that gets updated each time an object is retrieved from the cache. Then when the cache gets over some specific size you can prune everything older then a certain timestamp. Of course that requires walking the entire cache to do that.
Since you are combining interfaces and a collection then if you have a reference to an object (via its interface), and it gets pruned during cache cleanup, then the object will remain alive until the reference goes away. This provides you an additional safety. Of course if you are still using the reference, then that means you kept the reference for a long time without retrieving it from the cache. In that case you may want to update the timestamp when you read or write to the properties too . . . A lot of that depends on how you will be using the business objects.
As far as refetching, you only want to do that if an object is retrieved from the cache that is older then the refetch limit. That way if it gets pruned before you use it again you are not wasting database trips.
You might consider just having a last modified time in each table. Then when you get an object from the cache you just check the time in memory against the time in the database. If the object has been changed since it was last retrieved, you can update it.
I would limit updating objects only to when they are being retrieved from the cache. That way you are less likely to modify the object while it is use. If you are in the middle of reading data from an object while it changes that can produce some really odd behavior. There are a few ways to handle that, depending on how you use things.
Word of warning about using interfaces, you should not have both object and interfaces references to the same object. Doing so can cause trouble with the reference counting and result in objects being freed while you still have an object reference.
I am sure there will be some feedback on this, so pick what sounds like the best solution for you. . . .
Of course now that I have written all of this I will suggest you look at some sort of business object framework out there. RemObjects has a nice framework, and I am sure there are others.
You might want to start by looking at smart pointers. Barry kelly has an implimentation for D2009.
For your BI objects, I would use a guid as the key field, or an integer that is unique across the database. As you load objects into memory, you could store them in a dictionary using the guid as the key and a container object as the value.
The container object contains the bi object, the ttl etc.
Before loading an object, check the dictionary to see if it is already there. If it is there, check the ttl and use it, or reload and store it.
For very fast "by name" lookup in your container object, I suggest you look not to trees, but to hash tables. The EZ-DSL (Easy Data Structures) library for Delphi includes the EHash.pas unit, which I use for my hashing containers. If you are interested in that, I will forward it to you.
I tend to think of "lifetime" oriented "containers" that delete all the objects they own when they close down.
I also think that you might consider making the objects themselves count their "usefulness", by having a "FLastUsed:Cardinal" data field. You can assign FLastUsed := GetTickCount and then have the system basically obey limits that you set up, maximum memory or instances to be actively used and how old an object should be (not used at all in X milliseconds) before it gets "demoted" to level 2, level 3, etc.
I am thinking that for Business Objects, you have a memory cost (keep it around when it could be really only a cache), and a coherency (flush my changes to the database before you can destroy me) constraint that makes traditional "garbage collection" ideas necessary, but not sufficient, for the whole problem of business object lifetime management.
For a higher level point of view, I recommend two books: "Patterns of Enterprise Application Architecture" by Martin Fowler and Eric Evans book about Domain-Driven Design, "Domain-Driven Design: Tackling Complexity in the Heart of Software" (http://dddcommunity.org/books#DDD). Martin Fowler explains all patterns for object management for business applications, including object repositories and different object / database mapping strategies. Eric Evans book "...provides a broad framework for making design decisions...".
There are aleady some (open source) O/R mapper libraries for Delphi with active community, maybe their source code also can provide some technical guidelines.
You are looking for a way to build a container that can store business objects and able to find already instanciated ones a runtime ?
Maybe you could give a look at http://www.danieleteti.it/?p=199 (Inversion of Control and Dependency Injection patterns.)