In this instance I am creating a queue implemented as a linked list. The queue has a pointer to the front and a pointer to the back.
Whenever I try to run the driver that tests the queue the program crashes shortly after starting an attempt at copying. My previous linked list program also had issues with the copy function, so I am unable to use it as a reliable reference.
The following code is my copy function:
template<class T>
void queue<T>::copy(const queue<T>& original){
QNodeType<T>* current;
QNodeType<T>* addin;
addin = new QNodeType<T>;
current = original.front_;
count=original.count;
if(front_ != NULL){
destroy();
}
if(original.front_==NULL){
front_=NULL;
back_=NULL;
}
else{
front_= new QNodeType<T>;
addin->item=current->item;
front_=addin;
back_=addin;
if(current->next != NULL){
while(current->next != NULL){
addin= new QNodeType<T>;
addin->item=current->item;
addin->next=NULL;
back_->next=addin;
back_=addin;
current=current->next;
}
}
}
}
Related
I call a function interleave that looks like
void AddressLinkedList::interleave(AddressLinkedList& other) {
AddressLinkedList temp;
AddressListNode* thisCur = this->head;
AddressListNode* otherCur = other.head;
for (int i = 0; i < this->length + other.length; i++) {
if (i % 2 == 0) {
temp.insertEnd(thisCur->data);
thisCur = thisCur->next;
}
else if (i % 2 != 0) {
temp.insertEnd(otherCur->data);
otherCur = otherCur->next;
}
}
return;
}
This function is supposed to interweave a singly linked list A with a singly linked list B along the lines of if A looked like "1, 2, 3" and B looked like "4, 5, 6", then the call linkedListA.interleave(linkedListB) should make A "1, 4, 2, 5, 3, 6". I've successfully managed to create a list like this, the problem is it that it's the temp list, but I don't know how to make it so it would be the this pointer with an end goal linkedListA be the aforementioned "singly linked list A". In case it matters, below is the overloaded assignment operator and the insertEnd function.
void AddressLinkedList::insertEnd(const Address& value) {
if (length == 0) {
this->insertStart(value);
return;
}
AddressListNode* temp = new AddressListNode(value);
length++;
tail->next = temp;
tail = temp;
}
AddressLinkedList& AddressLinkedList::operator=(const AddressLinkedList& other) {
delete this;
AddressListNode* current;
current = other.head;
while (current != nullptr) {
insertEnd(current->data);
current = current->next;
}
return *this;
}
Since interleave is defined as a member function of AddressLinkedList it should modify (and work on) the object it was called on. So you don't need to (and you shouldn't) create a temporary list to use it to build your resulting collection and then "assign" it as this. It is possible with some new, delete and raw pointer trickery, but I wouldn't recommend this (the idea would be to create AddressListNode* as head and then assign that new head where the original one was, but you would also had to delete previous chain of AddressListNode* from original head to avoid memory leaks, as I said, not recommended).
Assuming that your code that calls this method looks like this:
AddressLinkedList A;
AddressLinkedList B;
... //inserting values to A and B
A.interleave(B);
Your interleave implementation should looks more like this (it's more of a proof on concept, than working solution, I didn't compiled it):
void AddressLinkedList::interleave(AddressLinkedList& other) {
AddressListNode* thisCur = head;
AddressListNode* otherCur = other.head;
while (thisCur != nullptr) { //assumig that last node points to nullptr
AddressListNode* nextNode = thisCur->next;
AddressListNode* otherNext = otherCur->next;
thisCur->next = otherCur; //attach it to node from other
thisCur = thisCur->next; //advance to next node
thisCur = nextNode; //reattach node that was originally after current
thisCur = thisCur->next; //advance again to next node
otherCur = otherNext ; //advance on other
}
other->head = nullptr; //loop above hijack nodes from other
}
All this code do is, it takes heads of both of your collection, iterate over this and for every node it attaches corresponding node from other. Effectively it will modify your object on which you originally called interleave method. However due to modifying AddressListNode pointer it will also destroy your original AddressLinkedList you passed as and argument to interleave. So you should probably modify it in a way that for thisCur->next = otherCur; actually create a copy of an Address and create new node.
As Doug Lea point in the [The java.util.concurrent Synchronizer Framework
][1]http://gee.cs.oswego.edu/dl/papers/aqs.pdf that
But because there are no applicable techniques for lock-free atomic insertion of double-linked list nodes using compareAndSet, this link is not atomically set as part of insertion; it is simply assigned.
pred.next = node;
after the insertion. This is reflected in all usages. The next link is treated only as an optimized path. If a node's successor does not appear to exist (or
appears to be cancelled) via its next field, it is always possible to start at the tail of the list and traverse backwards using the pred field to accurately
check if there really is one.
the add node to sync queue code snippet is, copied form AbstractQueuedSynchronizer source code :
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) { // Must initialize
if (compareAndSetHead(new Node()))
tail = head;
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
my question is, in the sourcecode, the next field of a Node class is a volatile object, if compareAndSetTail success, then the next field of t must not be null, why there may be a null situation. the code snippet is:
static final class Node {
//....ignored
volatile Node next;
volatile Node prev;
//.... ignored
}
Also, I don't quite understand hasQueuedPredecessors. If h != t, then h's next filed should not be null, why h.next == null also means hasQueuedPredecessors?
public final boolean hasQueuedPredecessors() {
// The correctness of this depends on head being initialized
// before tail and on head.next being accurate if the current
// thread is first in queue.
Node t = tail; // Read fields in reverse initialization order
Node h = head;
Node s;
return h != t &&
((s = h.next) == null || s.thread != Thread.currentThread());
}
I wrote this program, and it crashes when I compile. It says the executable has stopped working and Windows is trying to find a solution. I believe the issue is somewhere in this addPage function I wrote to add a node to a linked list, but I'm not sure what is causing the issue.
void initPage(struct page *head, string programName) {
// Assign Properties of the First Node in the Linked List
head->programName = programName;
head->nextPage = NULL;
}
void addPage(struct page *head, string programName) {
// Initialize First Page if Not Initialized
if (head == NULL) {
initPage(head, programName);
return;
}
// Setup the New Page
page *newPage = new page;
newPage->programName = programName;
newPage->nextPage = NULL;
// Set the Pointer to the Beginning of the Linked List
page *current = head;
// While Traversing the Linked List
while(current) {
// If the End of the List is Reached, Append the Page
if (current->nextPage == NULL) {
current->nextPage = newPage;
return;
}
// Grab the Next Page (If not at the End of the Page)
current = current->nextPage;
}
}
This:
if (head == NULL) {
initPage(head, programName);
passes a null to initPage, which then immediately dereferences it. Boom.
Tip: ALWAYS check a pointer for null before using it.
Also, initPage is an incomplete copy of code in addPage. It seems better to always run the code in addPage that creates the new page (i.e., don't call initPage() at all) and then, once you've got a page, test head for null to see if you should just set head to the new page or iterate the list looking for the end.
Helly everyone,
I took a C++ coding course with practically no prior knowledge(my understanding of pointers is still somewhat shakey)at University this semester.
I have to implement a binary search tree in C++ and my problem is as follows:
Over a predefined Node structure with values and pointers to a left and a right node I am supposed to implement several functions, two of them being:
void InsertNode(Node* root, Node* node)
which is supposed to fit the handed node into the given tree "root",
and another one called
void InsertValue(Node* root, int value)
which should create a new instance of the node struct with the passed value and fit it in the given tree "root". To do so I am supposed to use both CreateNode (simple function to create Node* pointer of a new Node instance with int value and left/right pointers set to NULL) and InsertNode.
Im kind of running in a treadmill here and i dont think i really understand how the functions are supposed to work(eg. the difference between them).
Yesterday i wrote this function:
void InsertNode(Node* root, Node* node){
if(root == NULL){
root = CreateNode(node->value);
}
else if(root->value < node->value){
if(node->left != NULL){
InsertNode(root, node->left);
}
else{
node->left = CreateNode(root->value);
}
}
else if(root->value > node->value){
if(node->right != NULL){
InsertNode(root, node->right);
}
else{
node->right = CreateNode(root->value);
}
}
}
Since im not really able to test these functions without the later functions that will actually build the tree with given nodes i was curious if i could get some help here with the next functions InsertValue(what is it supposed to do that InsertNode doesnt do already? :S)
Greetings and thanks in advance.
Initial note: This answer assumes that the InsertNode function is initially called with root being the root of the tree, and node being the node to insert into the tree.
One problem is this statement:
root = CreateNode(node->value);
Since the argument root is passed by value, which means that it is copied, the assignment will only change the local copy. Once the function returns the original pointer that you pass to the function will not have changed.
You need to pass the pointer by reference, meaning the root argument references the original variable passed in to the function, instead of it being copied. You do this by using an ampersand when declaring the argument:
Node*& root
The above means that root is a reference to a pointer to Node.
So the complete InsertNode declaration should look like
void InsertNode(Node*& root, Node* node)
There are also other problems, for example these lines are not correct:
if(node->left != NULL){
InsertNode(root, node->left);
}
else{
node->left = CreateNode(root->value);
}
This is not correct because node->left should be NULL always, which makes you create a new node using the value from the root of the tree, and assign it to node->left, but you never insert node in the tree.
What you should instead do is simply
InsertNode(node->left, node);
Of course you should do the same change for setting the right branch.
Combining the two solutions above, your function would look like
void InsertNode(Node*& root, Node* node)
{
if (root == 0)
root = node;
else if (root->value < node->value)
InsertNode(root->left, node);
else
InsertNode(root->right, node);
}
This function also solves a third problem with your current code: What if node->value is equal to root->value? The above function puts it in the right branch.
When you are creating a tree, value are also assigned with each node. See following code:
typedef struct BST {
int data;
struct BST *lchild, *rchild;
} node;
void insert(node *root, node *new_node) {
if (new_node->data < root->data) {
if (root->lchild == NULL)
root->lchild = new_node;
else
insert(root->lchild, new_node);
}
if (new_node->data > root->data) {
if (root->rchild == NULL)
root->rchild = new_node;
else
insert(root->rchild, new_node);
}
}
node *new_node, *root;
int main()
{
new_node = get_node();
printf("\nEnter The Element ");
scanf("%d", &new_node->data);
if (root == NULL) /* Tree is not Created */
root = new_node;
else
insert(root, new_node)
}
The below code is in Python and is used for insertion in a BST ::
class Node :
def __init__(self.key):
self.left = None
self.right = None
self.val = key
def insert(root.node):
if root is None :
root = node
else :
if root.val < node.val:
if root.right is None :
root.right = node
else :
insert(root.right, node)
else :
if root.left is None :
root.left = node
else :
insert(root.left, node)
def inorder(root):
if root :
inorder(root.left)
print(root.val)
inorder(root.right)
# Driver program to test the above functions
# Let us create the following BST
# 50
# / \
# 30 70
# / \ / \
# 20 40 60 80
r = Node(50)
insert(r,Node(30))
insert(r,Node(20))
insert(r,Node(40))
insert(r,Node(70))
insert(r,Node(60))
insert(r,Node(80))
# Print inoder traversal of the BST
inorder(r)
I am writing a program that adds, deletes, and displays nodes (that are doubly linked) and their components, but whenever I try to retrieve a node and display it's components I get this error:
2 [main] a 4640 exception::handle: Exception: STATUS_ACCESS_VIOLATION
2875 [main] a 4640 open_stackdumpfile: Dumping stack trace to a.exe.stackdump
I have narrowed it down to the search function within my .h file that is supposed to search to see if there is a node within the linked list that account number being searched. The function returns the node that comes before it, or the "previous" node.
Here is my search function:
bool searchListByAcctNum (int searchKey, nodePtr *prevOut)
{
bool found = false;
nodePtr p = headNum;
nodePtr prev = NULL;
while (p != NULL)
{
if (p->acctNum < searchKey)
{
prev = p;
p = p->nextNum;
}
else
{
if (p->acctNum == searchKey)
found = true;
p = NULL;
}
}
*prevOut = prev;
return found;
If anyone could help me at all, I'd appreciate it!
It looks like your list may be corrupted, or the pointer you're passing to receive the previous node is invalid, since that code looks okay. However, it seems to me that it could be written in a much simpler manner:
bool searchListByAcctNum (int searchKey, nodePtr *prevOut) {
/// Start at beginning of list, use pointer variable to hold previous.
nodePtr p = headNum;
*prevOut = = NULL;
// Process entire list, will exit early if need be.
while (p != NULL) {
// If past it, just return false, caller should ignore prevOut.
if (p->acctNum > searchKey)
return false;
// If equal, return true, prevOut holds previous or NULL if found at start.
if (p->acctNum == searchKey) {
return true;
// Save previous and advance to next.
*prevOut = p;
p = p->next;
}
// Reached end of list without finding, caller should ignore prevOut.
return false;
}