Gamestudio Links
Zorro Links
Newest Posts
Help with plotting multiple ZigZag
by degenerate_762. 04/30/24 23:23
M1 Oversampling
by 11honza11. 04/30/24 08:16
Trading Journey
by howardR. 04/28/24 09:55
Zorro Trader GPT
by TipmyPip. 04/27/24 13:50
Data from CSV not parsed correctly
by jcl. 04/26/24 11:18
AUM Magazine
Latest Screens
The Bible Game
A psychological thriller game
SHADOW (2014)
DEAD TASTE
Who's Online Now
3 registered members (AndrewAMD, dr_panther, Quad), 935 guests, and 3 spiders.
Key: Admin, Global Mod, Mod
Newest Members
firatv, wandaluciaia, Mega_Rod, EternallyCurious, howardR
19050 Registered Users
Previous Thread
Next Thread
Print Thread
Rate Thread
Doubly Linked List for lite-C #457124
12/27/15 20:40
12/27/15 20:40
Joined: Nov 2010
Posts: 8
Berlin
OCMvL Offline OP
Newbie
OCMvL  Offline OP
Newbie

Joined: Nov 2010
Posts: 8
Berlin
EDIT: The list contained 3 errors that would lead to crashes.
EDIT 2: Several changes due to feedback and other requirements.

Hey all,

Just wrote a little data structure that imitates a doubly linked list from C++'s STL.

This implementation doesn't support everything a list can do, like sorting. Check out the header file for the given functionality.

Unfortunately there is no template functionality in C, so the structure only works with one specific data type. If you need to use lists for various data types, copy the .h and .c files and change the data type and the prefix name. You don't have to duplicate every single function, but I would recommend to do so, since it's more versatile. This list works with char*

For example:
Code:
CListInt.h
CListInt.c
typedef struct CListIntNode
CListInt* CListIntCreate();

CListChar.h
CListChar.c
typedef struct CListCharNode
CListChar* CListCharCreate();

etc.



Ok, so here's how you would use it, and below you find the implementation.
Code:
#include <acknex.h>
#include <default.c>

#include "CList.c"

function main()
{
	CList* mylist = CListCreate();
	
	CListDisplay(mylist);
	
	CListPush(mylist, "Bob");
	CListPush(mylist, "Max");
	CListPush(mylist, "Olly");
	CListPush(mylist, "John");
	CListPush(mylist, "Jim");
	CListPush(mylist, "Olly");
	CListPush(mylist, "Olly");

	CListNode* node = CListFindNode(mylist,"Olly"); // Get the first node that matches "Olly"
	if(node != NULL) CListRemoveNode(mylist, node);

	CListRemoveValue(mylist,"Olly"); // Removes every item that contains "Olly"
	
	CListEraseIndex(mylist, 1); // Remove Max
	
	CListNode* it = CListBegin(mylist);
	while( it != NULL )
	{
		if( str_cmp(it.data,"John") || str_cmp(it.data,"Jim") )
		{
			CListRemoveNode(mylist, it);
		}
		it = CListNext(mylist);
	}
	
	CListDisplay(mylist);
	CListFree(mylist);
	mylist = NULL;
}



Header file (CList.h):
Code:
/*
	Header file for CList class
	Author: Oliver Mistarz
	Purpose: C Doubly Linked List
*/

typedef struct CListNode {
	char* data; // CHNANGE DATA TYPE
	struct CListNode* previous;
	struct CListNode* next;
} CListNode;

typedef struct CList {
	CListNode* firstnode;
	CListNode* lastnode;
	CListNode* iterator;
	CListNode* nextiterator;
	int length;
} CList;

CList* CListCreate();
CListNode* CListBegin(CList* _list);
CListNode* CListNext(CList* _list);
function CListPush(CList* _list, char* _data); // CHNANGE DATA TYPE
int CListLength(CList* _list);
int CListFindIndex(CList* _list, char* _data); // CHNANGE DATA TYPE
CListNode* CListFindNode(CList* _list, char* _data); // CHNANGE DATA TYPE
function CListRemoveFront(CList* _list);
function CListRemoveBack(CList* _list);
function CListRemoveNode(CList* _list, CListNode* _node);
function CListRemoveValue(CList* _list, char* _value); // CHNANGE DATA TYPE
function CListRemoveIndex(CList* _list, int position);
function CListDisplay(CList* _list);
function CListDispose(CList* _list);
function CListFree(CList* _list);



Code file (CList.c):
Code:
#ifndef CList_C
#define CList_C
#include "CList.h"

CList* CListCreate()
{
	CList* this = malloc(sizeof(CList));
	memset(this, 0, sizeof(CList));
	
	this.firstnode = NULL;
	this.lastnode = NULL;
	this.iterator = NULL;
	this.nextiterator = NULL;
	this.length = 0;
	
	return this;
}

CListNode* CListBegin(CList* _list)
{
	if(_list.firstnode != NULL)
	{
		_list.iterator = _list.firstnode;
		_list.nextiterator = _list.iterator.next;
		return _list.iterator;
	}
	return NULL;
}

CListNode* CListNext(CList* _list)
{
	if(_list.nextiterator != NULL)
	{
		_list.iterator = _list.nextiterator;
		_list.nextiterator = _list.iterator.next;
		return _list.iterator;
	}
	return NULL;
}

function CListPush(CList* _list, char* _data) // CHNANGE DATA TYPE
{
	CListNode* newnode = malloc(sizeof(CListNode));
	memset(newnode, 0, sizeof(CListNode));
	newnode.data = _data;
	
	if(_list.firstnode != NULL)
	{
		newnode.previous = _list.lastnode;
		newnode.next = NULL;
		
		_list.lastnode.next = newnode;
		_list.lastnode = newnode;
	}
	else
	{
		newnode.previous = NULL;
		newnode.next = NULL;
		
		_list.firstnode = newnode;
		_list.lastnode = newnode;
	}
	
	_list.length++;
}

int CListLength(CList* _list)
{
	return _list.length;
}

int CListFindIndex(CList* _list, char* _data) // CHNANGE DATA TYPE
{
	CListNode* link;
	int count;
	for(link = _list.firstnode, count = 0; link != NULL; link = link.next, count++)
	{
		if( link.data == _data )
		{
			return count;
		}
	}
	return -1;
}

CListNode* CListFindNode(CList* _list, char* _data) // CHNANGE DATA TYPE
{
	CListNode* link;
	int count;
	for(link = _list.firstnode, count = 0; link != NULL; link = link.next, count++)
	{
		if( link.data == _data )
		{
			return link;
		}
	}
	return NULL;
}

function CListRemoveFront(CList* _list)
{
	if( _list.firstnode != NULL )
	{
		if( _list.firstnode == _list.lastnode )
		{
			free(_list.firstnode);
			_list.firstnode = NULL;
			_list.lastnode = NULL;
		}
		else
		{
			CListNode* tmpDel = _list.firstnode;
			_list.firstnode.next.previous = NULL;
			_list.firstnode = _list.firstnode.next;
			free(tmpDel);
			tmpDel = NULL;
		}
		_list.length--;
	}
}

function CListRemoveBack(CList* _list)
{
	if( _list.firstnode != NULL )
	{
		if( _list.firstnode == _list.lastnode )
		{
			free(_list.firstnode);
			_list.firstnode = NULL;
			_list.lastnode = NULL;
		}
		else
		{
			CListNode* tmpDel = _list.lastnode;
			_list.lastnode.previous.next = NULL;
			_list.lastnode = _list.lastnode.previous;
			free(tmpDel);
			tmpDel = NULL;
		}
		_list.length--;
	}
}

function CListRemoveNode(CList* _list, CListNode* _node)
{
	if( _list.firstnode != NULL )
	{
		if( _node == _list.firstnode )
		{
			CListRemoveFront(_list);
		}
		else if( _node == _list.lastnode )
		{
			CListRemoveBack(_list);
		}
		else
		{
			_node.previous.next = _node.next;
			_node.next.previous = _node.previous;
			free(_node);
			_list.length--;
		}
	}
}

function CListRemoveValue(CList* _list, char* _value) // CHNANGE DATA TYPE
{
	CListNode* link;
	for(link = _list.firstnode; link != NULL; link = link.next)
	{
		if( link.data == _value )
		{
			CListRemoveNode(_list,link);
		}
	}
}

function CListRemoveIndex(CList* _list, int position)
{
	if( position >= CListLength(_list) || position < 0 )
	{
		printf("Index out of bounds");
		return;
	}
	
	CListNode* link;
	int count;
	for(link = _list.firstnode, count = 0; link != NULL; link = link.next, count++)
	{
		if( count == position )
		{
			CListRemoveNode(_list, link);
			return;
		}
	}
}

function CListDisplay(CList* _list)
{
	CListNode* link;
	for(link = _list.firstnode; link != NULL; link = link.next)
	{
		printf("data: %s", link.data); // CHNANGE DATA TYPE
	}
}

function CListDispose(CList* _list)
{
	CListNode* tmp;

	if(_list.firstnode != NULL)
	{
		_list.iterator = _list.firstnode;
		_list.firstnode = NULL;
		while( _list.iterator != NULL )
		{
			tmp = _list.iterator.next;
			free(_list.iterator);
			_list.iterator = tmp;
		}
	}
}

function CListFree(CList* _list)
{
	CListDispose(_list);
	free(_list);
}

#endif


Have fun!

Last edited by OCMvL; 01/02/16 10:51. Reason: Bugfixes & Changes
Re: Doubly Linked List for lite-C [Re: OCMvL] #457130
12/28/15 12:07
12/28/15 12:07
Joined: Mar 2011
Posts: 3,150
Budapest
sivan Offline
Expert
sivan  Offline
Expert

Joined: Mar 2011
Posts: 3,150
Budapest
thanks, it seems to be very useful.


Free world editor for 3D Gamestudio: MapBuilder Editor
Re: Doubly Linked List for lite-C [Re: OCMvL] #457167
01/01/16 14:44
01/01/16 14:44
Joined: Nov 2010
Posts: 8
Berlin
OCMvL Offline OP
Newbie
OCMvL  Offline OP
Newbie

Joined: Nov 2010
Posts: 8
Berlin
Fixed 3 bugs that would lead to crashes and memory leaks.
Especially when you store pointers in the list.
Please update the CList.c file.

Re: Doubly Linked List for lite-C [Re: OCMvL] #457170
01/01/16 20:13
01/01/16 20:13
Joined: Apr 2007
Posts: 3,751
Canada
WretchedSid Offline
Expert
WretchedSid  Offline
Expert

Joined: Apr 2007
Posts: 3,751
Canada
There are several bugs/issues in this, for example, the find function returns an undefined value when it doesn't find the node, i.e., it is impossible to tell if a value exists. Furthermore, deleting by index is an O(n2) operation worst case, because the length function is, for whatever reason, an O(n) operation. And it's the only really usable deletion function because there is no find function which returns a node directly.


Shitlord by trade and passion. Graphics programmer at Laminar Research.
I write blog posts at feresignum.com
Re: Doubly Linked List for lite-C [Re: WretchedSid] #457171
01/01/16 20:15
01/01/16 20:15
Joined: Apr 2007
Posts: 3,751
Canada
WretchedSid Offline
Expert
WretchedSid  Offline
Expert

Joined: Apr 2007
Posts: 3,751
Canada
Plus, what's up with the iterator members? They are completely unnecessary and only add complexity.


Shitlord by trade and passion. Graphics programmer at Laminar Research.
I write blog posts at feresignum.com
Re: Doubly Linked List for lite-C [Re: WretchedSid] #457175
01/02/16 10:57
01/02/16 10:57
Joined: Nov 2010
Posts: 8
Berlin
OCMvL Offline OP
Newbie
OCMvL  Offline OP
Newbie

Joined: Nov 2010
Posts: 8
Berlin
Thanks for the feedback.


Moderated by  HeelX, Lukas, rayp, Rei_Ayanami, Superku, Tobias, TWO, VeT 

Gamestudio download | chip programmers | Zorro platform | shop | Data Protection Policy

oP group Germany GmbH | Birkenstr. 25-27 | 63549 Ronneburg / Germany | info (at) opgroup.de

Powered by UBB.threads™ PHP Forum Software 7.7.1