Reputation: 3513
GLib library done like this to compare two singly linked list nodes:
typedef struct _GSList {
_GSList *link;
void *data;
} GSList;
int g_sListPosition(GSList *list, GSList *llink) {
int cnt = 0;
while(list) {
if(list == llink) // Note here
return cnt;
cnt++;
list = list->link;
}
return -1;
}
But when I compare the nodes like this. It return false:
int main(void) {
GSList *list = NULL, *list2 = NULL;
list2 = g_sListAppend(list2, "def");
list = g_sListAppend(list, "abc");
list = g_sListAppend(list, "def");
list = g_sListAppend(list, "ghi");
printf("%d", g_sListPosition(list, list2)); // Return -1 ?
}
So, what's compare here (in the DOC, it's written gets the position of the given element in the GSList), a node or the data contained in the list ?
Edit: Thanks to all the given, my mistake I was actually doing it in wrong way. I have to compare same instance of the list.
Upvotes: 2
Views: 13697
Reputation: 61910
The list with head list2
+--------+
| def |--->X
+--------+
arr1
When the function allocates the node it will allocate a free memory location with the size of the node and then assign the string in the node's data part (where it has to assign the string).
The list with head list
+--------+ +--------+ +--------+
| abc |--->| def |--->| ghi |--->X
+--------+ +--------+ +--------+
addr2 addr3 addr4
Here everytime you append a string to the linked list, a new node is allocated and the string is copied in the data part. Note that, everytime a new node is allocated the address of the node is different.
In the case above the first list with the data "def" has address addr1
and the second list has the node with data "def" has the address addr3
. So if you try to compare these two nodes with the ==
operator, naturally the comparison result will be false because the equality will compare the address of the nodes, which are different and thus return false.
If you want to particularly match a data in the node you need to compare it specifically. Which is, visit each node in list
and compare the data part with the other node (list1
).
On the other hand, if you to have exacted the node address inside a specific linked list, then you can use the address to compare. For example if you traverse the list till the end and get the address of the last node with "ghi" in it having address addr4
, then you can use this address to compare that specific node inside the list later, provided that this node has not been freed and re-created with same data. In such case as you can see clearly even the data inside this node changes the address will remain the same.
Upvotes: 2
Reputation: 58271
Because list
and llink
are node address and we can't have two different nodes with same address, its very simple technique to find where llink
start within in list
(first).
Suppose list
passes to function is like:
// 0 1 2 3 4
list---->[]-->[]-->[]-->[]-->[]---null
23 42 18 102 324
addresses are assumption
if llink
value is 18
, then function returns 2
because llink
is third node in list
.
and if llink
not found it returns -1
.
(like array index starts with 0
function count numbers node in list from 0
)
As you commented I am commenting code:
int cnt = 0; // initial value of node_count is 0
while(list) { // search while list not NULL (till end)
if(list == llink) // if `llink` is a node in `list`
return cnt; // return node number
cnt++; // else it may be next node
list = list->link;
}
// control comes here if list == NULL, means llink not found
return -1; // not found so return -1
// negative number can't be a position
comment:
I mean, how to test it If it really gives positive value
Call your function as below:
g_sListPosition(list, list->link->link->link);
// 0 1 2
it will return 2
.
but note you list should be consists of 3
nodes.
Upvotes: 2
Reputation: 3513
I found that, we have to actually give the same instance of the list. Here's an example below:
int main(void) {
RSList *list = NULL;
list = r_sListAppend(list, "abc");
list = r_sListAppend(list, "def");
list = r_sListAppend(list, "ghi");
RSList *list2 = list;
int i = 2;
while(i--) {
list2 = list2->link;
}
printf("%d", r_sListIndexOf(list, list2)); // Print 2
}
Upvotes: 0