Now, I am doing a exercise in introduction to algorithms by using C++.
The question is :
Explain how to implement doubly linked lists using only one pointer
value x.np per item instead of the usual two (next and prev). Assume
that all pointer values can be interpreted as k-bit integers, and
define x.np = x.next XOR x.prev, the k-bit "exclusive-or" of x.next
and x.prev. (The value NIL is represented by 0). Be sure to describe
what information you need to access the head of the list. Show how to
implement the SEARCH, INSERT and DELETE operations on such a list.
Also show how to reverse such a list in O(1) time.
In the XOR function, I first convert pointer to class into unsigned long and Xor these two value. And then convert the result back to a pointer to class. I don't know why it doesn't work. Here is my code:
struct node
{
int key;
node *np;
} ;
struct list_n
{
node *head;
node *tail;
};
The above are two structs and below is insertion
void insert_element(list_n *_list, int _key)
{
node *present_node= new node;
present_node->key=_key;
present_node->np=xor_gate(nullptr,_list->tail);
if(_list->tail) _list-> tail->np=xor_gate(present_node,xor_gate(nullptr,_list->tail->np ));
if(!_list->head) _list->head=present_node;
_list->tail=present_node;
}
Below is the Xor gate :
node *xor_gate(node *left,node *right)
{
unsigned long result;
result = ( reinterpret_cast<unsigned long>(left) ) ^ ( reinterpret_cast<unsigned long>(right) );
node *output =new node;
output = reinterpret_cast<node*> (result); // yes or no
return output ;
}
void list_n_inti(list_n *a )
{
a->head =nullptr;
a->tail =nullptr;
}
I have review the code several times. I think the problem is caused by XOR gate.
If you have found the bug please tell me. And if you have any other ways to answer this question. please tell me.
Thank you
There is a memory leak in xor_gate, but I think the code works if you compile it as 32-bits. If you compile it as 64-bits, then unsigned long cannot contain a pointer generally.
try this:
#include <cstdint> // for uintptr_t
node *xor_gate(node *left,node *right)
{
using std::uintptr_t;
uintptr_t result = ( reinterpret_cast<uintptr_t>(left) ) ^ ( reinterpret_cast<uintptr_t>(right) );
return reinterpret_cast<node*> (result);
}
Related
I am having a hard time understanding how this code is working . I always thought before using pointer to a structure , it should be defined. In the below example why compiler doesn't complain about struct LL* Next ?
typedef struct LL
{
int value;
**struct LL* Next;**
}Node;
Node* temp;
In your code,
struct LL* Next;
is allowed as a member inside the struct LL definition itself and does not throw any error, because, at that point, compiler need not know about the definition of the structure itself. It just needs to allocate a pointer to the structure, and so it can.
Later, while using a variable of the struct type, you have to allocate memory for the pointee and assign that memory to the pointer before any further usage.
You are allowed to use an incomplete type (lacking sufficient information to determine the size of objects of that type) in a struct definition. When you write struct LL* Next; in the definition of struct LL, LL has already been declared as a struct, so no errors are thrown.
In fact, N1570 has provided some examples about this:
10 EXAMPLE 1 This mechanism allows declaration of a self-referential
structure.
struct tnode {
int count;
struct tnode *left, *right;
};
specifies a structure that contains an integer and two pointers to
objects of the same type. ......
11 The following alternative formulation uses the typedef mechanism:
typedef struct tnode TNODE;
struct tnode {
int count;
TNODE *left, *right;
};
TNODE s, *sp;
"Variables should always be initialized" is a rule of thumb. It's not a great rule, and sometimes (like in your example), it must be violated, at least temporarily. Uninitialized data (garbage) does not cause problems on its own.
Some programmers will religiously initialize their variables like this.
int i = 0;
Node * foo = NULL;
Nothing forces you to do that. It's just programmers doing unnecessary things.
Initializing your pointers to something meaningful before dereferencing them is important though.
#include <stdio.h>
#include <stdlib.h>
typedef struct LL
{
int value;
struct LL* next;
}Node;
int main (int argc, char ** argv)
{
Node * A; // OK. A points at garbage.
Node * B; // OK. B points at garbage.
B = A; // Dumb, but OK. B now points at the same garbage as A.
B = A->next; // ERROR. You can't dereference garbage.
A = malloc (sizeof(Node)); // A is no longer points at garbage. The newly created A->value and A->Next are garbage though.
B = A->next; // Dumb, but OK. B now points at the same garbage as A->Next.
B->value = 200; // ERROR. B is garbage, you can't dereference garbage.
A->value = 100; // OK. A->value was garbage, but is now 100.
// *********************************
// Enough academic examples. Let's finish making the linked list.
A->next = malloc(sizeof(Node)); // OK. A->value no longer points at garbage.
B = A->next; // OK. B now points at the second node in the list.
B->value = 200; // OK. B->value was garbage, is now 200.
B->next = NULL; // OK. B->Next was garbage, is now NULL.
printf("A: %#x, value: %d, next: %#x\n", A, A->value, A->next);
printf("B: %#x, value: %d, next: %#x\n", B, B->value, B->next);
return 0;
}
I am trying to use tagged pointers for handling the lock free operations on a list, in order to block the compare-and-swap (CAS) from going through if some other thread operated on the list during this transaction. My node struct and CAS look like this:
struct node {
unsigned long key;
unsigned long val;
struct node * next;
};
static inline bool CAS(std::atomic<node*> node, struct node* oldNode, struct node* newNode)
{
node.compare_exchange_strong(oldNode, newNode, std::memory_order_seq_cst);
}
I found some methods for setting and checking these pointers but it is unclear to me how they work, these are the methods for setting the mask and verifying it.
__inline struct node* setTagMask(struct node* p, int MASK_BIT)
{
return (struct node*) ((uintptr_t)p | MASK_BIT);
}
__inline bool isMaskFlagSet(struct node* p)
{
return ((uintptr_t)p & MASK_BIT) != 0;
}
So what is unclear to me is for example in the setTagMask, if I use it on my list than it will delete all its references to its value and next element as well.
Can anyone explain to me how can I properly set these bits so the other elements of the list remain the same?
The setTagMask function returns a modified version of the pointer p. If you store this modified pointer in your linked-list, then the list gets broken because the modified pointer does not point to a node anymore.
The pointer is modified as follows. The pointer p is converted to an unsigned integer which is capable to store a pointer: uintptr_t.
Then one or more bits are set according to MASK_BIT. Finally, the result is converted back to a pointer and returned.
The function isMaskFlagSet checks whether the mask bits are still set.
The only use case, I can image is: you have to call isMaskFlagSet every time, before you use the pointer. If the mask bits are set, then it is prohibited to actually use the pointer.
Perhaps this is a stupid question, but the reason I ask is because I'm using strcmp() to compare a dynamic array with a static array and it's seemingly giving the wrong result. The arrays should be equal, but strcmp() is returning false. When I pause my program, the only two things that differ between those arrays are their memory locations.
I can't show you the whole code, but here's part of my function which has these two variables in it:
stock * Table::retrieveStock(const char tick[])
{
uint8_t index = hashing(tick);
if (table[index])
{
bool test = strcmp(table[index]->data->getTick(), tick);
//irrelevant code
and here's how some of the pointers are declared in the Table class:
struct node
{
stock * data;
node * next;
node()
{
stock();
next = nullptr;
}
node(stock *& item)
{
data = item;
next = nullptr;
}
};
node ** table;
I have an array of class objects in it, anyways, the point is that I'm comparing two tick values, which should be equal. One I'm pulling out of the object with the getTick() function:
const char * stock::getTick() const
{
return tick;
}
and one is passed into the function: const char tick[]. I'm quite clueless as to what is wrong with my code here. I would love to give you guys more code to work with, but I can't see how it would do anything but make solving this issue more difficult for you.
Edit: Maybe this will help; I just thought of it. This is exactly what my compiler says the values are:
curr->data 0x005d93e8 {tick=0x005d9f38 "TSLA" name=0x005da100 "2" value=2.00000000 ...} stock *
and
tick 0x004afb20 "TSLA" const char *
strcmp() returns 0 for a match (and non-zero for no match). It doesn't return true or false as you are expecting.
I am trying to make a memory efficient doubly linked list. The list stores the XOR of the next and the previous addresses, but I am facing an error in the function XOR. The error is:
[Error] cast from 'node*' to 'unsigned int' loses precision [-fpermissive]
My code is:
#include<bits/stdc++.h>
using namespace std;
struct node
{
int data;
node *next;
}*start,*temp;
node* XOR(node *a,node *b)
{
return (node *)((unsigned int)(a)^(unsigned int)(b));
}
void push(int data)
{
node *a=new node;
a->data=data;
a->next=XOR(start,NULL);
if(start!=NULL)
start->next=XOR(start->next,a);
start=a;
}
void disp()
{
temp=start;
node *prev,*cur;
while(temp)
{
cout<<temp->data<<" ";
if(temp==start)
{
prev=temp;
temp=temp->next;
}
else
{
cur=temp;
temp=XOR(temp->next,prev);
prev=cur;
}
}
}
main()
{
start=NULL;
push(1);
push(2);
push(3);
push(4);
push(5);
push(6);
push(7);
push(8);
}
An unsigned int is not guaranteed to be as large as a a pointer, in many cases a pointer is 64 bits and an unsigned int 32 bits. Therefore in this case the upper 32 bits are discarded, invalidating the pointer. You need a uintptr_t instead of an unsigned int.
The corrected code must first:
#include <cstdint>
Somewhere at the top in order to add a declaration for uintptr_t as well as a variety of other useful types and second change the line:
return (node *)((unsigned int)(a)^(unsigned int)(b));
To:
return (node *)((uintptr_t)(a)^(uintptr_t)(b));
Please take a look here for a much better explanation of how uintptr_t and other similar types work http://www.cplusplus.com/reference/cstdint/
Finally I shall mention that in most modern machines a xored linked list will actually be slower, not faster than a normal doubly linked list as the technique makes it much harder for the CPU and compiler to predict what you are doing and optimise well and this effect is greater than the speed boost from small space saving.
You should use uintptr_t defined in #include <cstdint>.
The very purpose of uintptr_t is to be capable of holding a void* pointer and being converted back without loss of precision.
Use
uintptr_t XOR(node *a,node *b)
{
return reinterpret_cast<uintptr_t>(a)^reinterpret_cast<uintptr_t>(b);
}
I wouldn't then cast that back to node* until you eventually return to a uintptr_t that is the valid pointer.
I don't believe it's well defined what happens when you cast a uintptr_t that wasn't directly cast from a pointer to a pointer.
Good day,
I just started to learn void pointers in c++ and now I'm writing binary tree where value stored in each node is void pointer to a value.
struct TreeNode
{
int count;
void* data;
TreeNode *left;
TreeNode *right;
};
The problem occurred in very first method-add method.
my method now takes int a a parameter and return nothing
At the very beginning i create new node.
To do that I need to cast integer into void.
Program compiles and first element adds to root correctly-however then when i send another number to method it stores in root again.
so if in main i have something like
tree.addToTree(12);
tree.addToTree(13);
than it would store 12 first and than right after else statement(code below)how that root->data i 13.
void Tree::addToTree(int num)
{
if(root==NULL){
root= new TreeNode();
root->data=#
//((int *)(root->data)) = num;//i tried to convert to void* in this way but it give me segmentation fault
root->left=NULL;
root->right=NULL;
}
else{
//here root value is already changed
int *intPtr = static_cast<int*>(root->data);
cout << "key2" << *intPtrT << endl;
//TreeNode* current= insert(num,root);
}
}
as i understood thats because i use &num so my parameter always tore in one place and a root is "connected" to &num it change as well.
I tried to find solution but was unsuccessful.
Is there a way to cat int to void pointer?
First of all, there are very very few reasons to store something as a void* instead of using a strongly typed method (e.g. template). Your entire problem goes away fairly quickly when you change your code to
template<typename T>
TreeNode
{
TreeNode<T>* left;
TreeNode<T>* right;
T data;
};
That said, the problem you have is that you are storing the address of a copy that will go away once the function goes out of scope:
if(root==NULL)
{
root= new TreeNode();
root->data=# // PROBLEM!!!
root->left=NULL;
root->right=NULL;
}
The problem line should be:
root->data = new int(num);
And you will have to properly delete the memory when you are done with it (e.g. when your tree is being destructed).
Alternatively, if you happen to be on a system where sizeof(void*) == sizeof(int), you can do this
root->data = (void*)num;
Which will simply treat the void* member as an integer. This does not work on systems where int is larger than void*.
First of all you should decide if you want to store data by value or by a pointer to it.
In first case having a pointer is just useless, you could use a template like:
template <typename T>
struct TreeNode
{
T data;
..
}
TreeNode<int> node;
This will work even with pointers (like T *data ... data = new int()).
In case you want to store a pointer to data you can also use a template with a type parameter or use a common ancestor class and then subclass it with the required types, eg:
class TreeData {
}
class TreeDataInt {
int value;
}
struct TreeNode
{
TreeData *data;
..
}
Lastly storying an int inside a void* pointer is something not so encouraged, using void* in C++ to achieve polymorphism is discouraged in general since you have many other tools which are safer and more reliable.
If you really want to store an int inside a void* then you should use the intptr_t type which is an integer that is convertible to a pointer. Eg:
#include <cstdint>
intptr_t value = 50;
node->data = static_cast<void*>(value);
intptr_t value2 = static_cast<intptr_t>(node->data);
This will save the value of the integer directly as an address inside the void*. This means that you can't dereference the pointer itself.
By the way root->data=&num is wrong since you are assigning to data the address of an automatic allocated variable which will become invalid when exiting its scope.
One problem I see is this (not the answer, just a problem)... in the function
void Tree::addToTree(int num)
{
if(root==NULL){
root= new TreeNode();
root->data=#
You are assigning the address of an automatic variable to data. The trouble is that as soon as the function exits, this variable will no longer exist (it is said to go out of scope) and so you have what's known as a dangling pointer, i.e., a pointer that points to an area of memory that is no longer used or is no longer used for the original purpose that the pointer expects.
You could fix this in three ways.
If you only want to store ints or any data type whose width is le that sizeof(void *), you could do root->data = (void *)num (note I cast the value of the variable to a void* and not the address of the variable). Or you could, as I see Zac has suggested too,
Create a copy of the variable and store the copies address. root->data = new int(num);. In this case you must make sure to delete the memory when you destroy the tree
Use templates as others have suggested (this is the better way) - I'll leave this point as others have covered it.
The other bit of you question where you have the comment
//((int *)(root->data)) = num;//i tried to convert to void* in this way but it give me segmentation fault
The reason this fails is because root->data at this point is just a pointer... it doesn't point anywhere (meaningful) yet. Thus when you try to dereference it, you are trying to access some memory that does "exist" yet (either pointer is NULL or has an invalid address), and so you seg fault.
When using a pointer in this way you need to create some memory and then make the pointer point to that memory, e.g. root->data = new int;. Once you have done that, you can then assign a value to that location in memory, e.g., *(root->data) = 1234;