The following is the actual Objective C class that implements a doubly-linked list (a variation of LinkedList). It can do the following:
- Addition of new elements to the front of the list
- Forward traversal using internal iterator
- Backward traversal
- Removal of the item the iterator points at
Here's the interface .h file:
//
// LinkedList.h
//
// Structure representing a
// doubly-linked list node.
typedef struct ListNode ListNode;
struct ListNode {
int value;
ListNode *next;
ListNode *prev;
};
@interface LinkedList : NSObject {
@private
ListNode *head;
ListNode *iterator;
//bool reachedHead;
//bool reachedTail;
}
- (id)initWithHead: (int)value;
- (void)addToFront: (int)value;
- (int)getFirst;
- (int)getCurrent;
- (int)getNext;
- (int)getPrevious;
- (bool)atHead;
- (bool)atTail;
- (int)removeCurrent;
@end
Now for the implementation .m file:
//
// LinkedList.m
//
#import "LinkedList.h"
@implementation LinkedList
/* Instantiates new linked list with a
* given first element.
*/
- (id)initWithHead: (int)value
{
ListNode *n;
self = [super init];
if (self) {
// creating head node with given value
n = (ListNode *)malloc(sizeof(ListNode));
n->value = value;
n->next = NULL;
n->prev = NULL;
head = n;
// initializing iterator to default
[self getFirst];
}
return self;
}
/* Adds a new element to the
* front of the list */
- (void)addToFront: (int)value
{
ListNode *n = (ListNode *)malloc(sizeof(ListNode));
n->value = value;
n->next = head;
n->prev = NULL;
// new element becomes the head node
head->prev = n;
head = n;
}
/* Sets internal iterator to
* the head node and returns its
* value */
- (int)getFirst {
iterator = head;
//reachedHead = TRUE;
//reachedTail = FALSE;
return (head->value);
}
/* Returns the value of the iterator node
*/
- (int)getCurrent {
return (iterator->value);
}
/* Iterates to the next node in order and
* returns its value */
/*
- (int)getNext
{
// if we are finished iterating,
// set the end-of-list flag
if (iterator->next == NULL) {
reachedTail = TRUE;
} else {
// if we're leaving the head
// node, set the flag
if (iterator->prev == NULL) {
reachedHead = FALSE;
}
iterator = iterator->next;
}
return (iterator->value);
}
*/
- (int)getNext
{
if (iterator->next != NULL) {
iterator = iterator->next;
}
return (iterator->value);
}
/* Iterates to the previous node in
* order and returns its value */
/*
- (int)getPrevious
{
if (iterator->prev == NULL) {
reachedHead = TRUE;
} else {
if (iterator->next == NULL) {
reachedTail = FALSE;
}
iterator = iterator->prev;
}
return (iterator->value);
}
*/
- (int)getPrevious
{
if (iterator->prev != NULL) {
iterator = iterator->prev;
}
return (iterator->value);
}
/* Indicates that iterator
* is at the first (head) node */
- (bool)atHead
{
//return reachedHead;
return (iterator->prev == NULL);
}
/* Indicates that iterator
* is at the last (tail) node */
- (bool)atTail
{
//return reachedTail;
return (iterator->next == NULL);
}
/* Removes the iterator node from
* the list and advances iterator to the
* next element. If there's no next element,
* then it backs iterator up to the previous
* element. Returns the old iterator value */
- (int)removeCurrent
{
int i = iterator->value;
ListNode *l;
// if we have only 1 item in the list...
if ((iterator->next == NULL) && (iterator->prev == NULL)) {
//... then we can safely delete it and set head to null
free(iterator);
iterator = NULL;
head = NULL;
} else {
// sawing the gap between nodes
l = iterator;
if (iterator->next != NULL) {
iterator->next->prev = iterator->prev;
}
if (iterator->prev != NULL) {
iterator->prev->next = iterator->next;
}
// finally setting new iterator
iterator = (iterator->next != NULL) ? iterator->next : iterator->prev;
free(l);
}
// returning old value
return i;
}
@end
So, essentially this is it. I assume the basic knowledge of how linked list operates. You can just plug in this class and use it in your programs, although I think several things need to be added for comfortable operation, like element search e.t.c. You can test this class with a test sniplet like the following:
#import <Foundation/Foundation.h>
#import "LinkedList.h"
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// insert code here...
LinkedList *test = [[LinkedList alloc] initWithHead: 0];
// testing addition
int i;
for (i = 1; i < 11; i++) {
[test addToFront: i];
}
NSLog(@"-- Added 10 values");
// testing forward traversal
NSLog(@"-- Setting iterator to first node: %d", [test getFirst]);
NSLog(@"-- Going forward until we hit the last element...");
do {
NSLog(@"---- Next element: %d", [test getNext]);
} while ([test atTail] == FALSE);
NSLog(@"-- We've hit the last element");
// testing back traversal
NSLog(@"-- Going back until we hit the first element...");
do {
NSLog(@"---- Previous element: %d", [test getPrevious]);
} while ([test atHead] == FALSE);
NSLog(@"-- We've hit the first element");
// testing removal
NSLog(@"-- Going forward 5 times");
for (i = 0; i < 5; i++)
NSLog(@"-- Next element: %d", [test getNext]);
NSLog(@"-- Current element with value %d", [test getCurrent]);
NSLog(@"-- Removing element with value %d", [test removeCurrent]);
NSLog(@"-- Continue forward traversal");
do {
NSLog(@"---- Next element: %d", [test getNext]);
} while ([test atTail] == FALSE);
NSLog(@"-- We've hit the last element");
NSLog(@"-- Returning to front, going forward until we reach end");
NSLog(@"-- First element: %d", [test getFirst]);
do {
NSLog(@"---- Next element: %d", [test getNext]);
} while ([test atTail] == FALSE);
NSLog(@"-- We've hit the last element");
[pool release];
return 0;
}