I'm learning C++ and learning linked lists. I'm currently trying to make a radix sort for this type of lists, but my approach is not working so I was wondering if anyone could advice me on how to do it. Here's my code:
void simpleList::radixSort() {
for (int i = 0; i < numberOfDigits(); i++){
Node * tmp = firstNode;
for (int j = 0; j < counter(); j++){
int pow = 10;
for (int k = 0; k < 10; k++){
if (tmp -> data % pow == k){
insertFirst(tmp->data);
tmp = tmp -> next;
}
pow= pow * 10;
}
}
}
}
The function numberOfDigits() gets you the amount of digits on the max number of the list, and counter() the amount of elements in the list. Also insertFirst() puts the number at the beggining of the list.
A few notes to help you on your way:
Radix Sort
A radix sort is any kind of (stable n-ary bucket sort) repeated until you run out of digits in your sort keys. Make your life simple: use binary as your radix.
Keys
You are using int values in your list, but that need not be the case. In general, you need a value→key function that returns an integer key for each element of your list, where “equivalent” elements return the same key. For a list of integers the value→key function is the identity function, so easy enough.
For convenience, I will use lambdas for the value→key functions below.
Reducing Passes
You can reduce the number of times you bucket sort to only those bits that are not the same for all keys. Before the first pass through your list, you do not know anything about the keys, so we can gather information at the same time as the first bucket sort:
key_type key_mask = 0; // bits to sort
key_type common_mask = ~0; // (bits set in all keys)
auto value_to_bucket_fn = [&]( const T & element )
{
// here we gather information about the keys
key_type key = user_supplied_value_to_key_fn( element );
key_mask |= key;
common_mask &= key;
// here we return our first bucket key == bit 0
return key & 1;
};
binary_bucket_sort( value_to_bucket_fn );
Once we have made that first pass, we can get a bitmask indicating which bits need sorting in our keys:
key_mask ^= common_mask; // key_mask ← set bits == bits to sort
All remaining passes can now be managed with a simple loop, ending when we run out of bits needing sorting:
for (int shift = 1; key_mask >>= 1; shift++)
if (key_mask & 1)
binary_bucket_sort( [&]( const T & element )
{
return (user_supplied_value_to_key_fn( element ) >> shift) & 1;
} );
Bucket Sort
A linked list is perfect for bucket sorts of large, unwieldly objects. Remember: the bucket sort must be stable, meaning it must not mix up the order of “equivalent” elements. This is imperative for a radix sort to work properly.
For a binary bucket sort over a linked list, life is pretty simple — only two buckets are necessary, and you only need keep track of the last node in each bucket to append.
If you are using a doubly-linked list that bookkeeping is done for you. If you are using a singly-linked list you will have to do it manually.
Node heads[2] = { Node{}, Node{} };
Node * tails[2] = { &heads[0], &heads[1] };
while (head)
{
int bucket = value_to_bucket_fn( head->data );
tails[bucket]->next = head; // append current head to correct bucket
tails[bucket] = head; // bucket’s new tail is the current head
head = head->next; // pop current head; get new current head
}
Hopefully you can see how easy this would be to expand to any number of buckets. Still, we will stick with two.
Once you have split all the nodes into the two buckets, just join them back together into your new complete list. Don’t forget to clean up the tail’s next pointer!
head = heads[0]->next;
tails[0]->next = heads[1]->next;
tails[1]->next = nullptr;
Be sure to check out trincot’s answer to see how he defined his singly-linked list with a lastNode pointer and useful functions to make all this splitting into buckets (“partitions”) and joining the final list into invocations of very inexpensive member functions.
Generics
This answer spends some time going on about keys and non-integer values. I have defined my list type’s nodes as:
struct node_type
{
T data;
node_type * next;
};
And I have defined the sorting functions as:
template <typename ValueToBucket>
void binary_bucket_sort( ValueToBucket value_to_bucket );
template <typename ValueToKey>
void radix_sort( ValueToKey value_to_key );
Then, when I sorted my test lists, I used variations of:
list <int> xs;
...
xs.radix_sort( []( int x ) { return x; } );
You can do things like observe the stability in the sort by playing with the value→key function (lambda). For example, I could define a list of integers where the one’s digit didn’t matter:
xs.radix_sort( []( int x ) { return x / 10; } );
Or a list of floats where the fractional part only mattered to two decimal places:
xs.radix_sort( []( double x ) { return static_cast <long long> ( x * 100 ); } );
I could have a list of Student where I am only interested in sorting by the student’s ID:
xs.radix_sort( []( const Student & student ) { return student.ID; } );
As long as the value→key function returns a sufficiently unique integer value we can use radix sort.
The main problem in your approach is that the only thing that can happen with a node is that it eventually gets moved to the start of the list. But there is nothing else that can happen with a node. For instance, there is no logic that leaves a node where it is and then moves on to the next. Instead the code keeps looking at the same node until it can be moved. It should be clear that this cannot result in a sorted order.
Secondly, if you are using radix 10, you will need 10 different possible destinations for a node ("buckets"), depending on the digit that is inspected. These would be linked lists as well, but you need to somehow manage them. Then when all nodes have been distributed over this buckets, the buckets should be joined again into a single list.
I would suggest using radix 2. Then you only need two "buckets". Also, I would suggest to keep track of the last node in a list (if you haven't already done so), with a lastNode member in your class.
Here is an implementation with radix 2 and the use of two bucket linked lists in each pass:
#include <iostream>
#include <vector>
class Node {
public:
Node *next = nullptr;
int data;
Node (int data): data(data) {};
Node (int data, Node *next): data(data), next(next) {};
};
class simpleList {
public:
Node *firstNode = nullptr;
Node *lastNode = nullptr;
simpleList() {}
simpleList(std::vector<int> data) {
for (auto value: data) {
append(value);
}
}
void clear() { // Does not free nodes
firstNode = lastNode = nullptr;
}
// Three variants of append. To append:
// * A node
// * A value, for which a Node will be created
// * Another linked list, which will be emptied
void append(Node *node) {
if (!firstNode) {
firstNode = node;
} else {
lastNode->next = node;
}
lastNode = node;
node->next = nullptr;
}
void append(int data) {
append(new Node(data));
}
void append(simpleList *other) {
if (firstNode) {
lastNode->next = other->firstNode;
} else {
firstNode = other->firstNode;
}
if (other->firstNode) {
lastNode = other->lastNode;
other->clear();
}
}
Node *popFirstNode() {
auto node = firstNode;
if (firstNode) {
firstNode = firstNode->next;
if (!firstNode) {
lastNode = nullptr;
}
node->next = nullptr;
}
return node;
}
void print() {
auto node = firstNode;
while (node) {
std::cout << node->data << " ";
node = node->next;
}
std::cout << "\n";
}
void radixSort() {
bool hasMoreBits = true;
simpleList *partitions[] = {new simpleList(), new simpleList()};
for (int bit = 0; hasMoreBits; bit++) {
hasMoreBits = false;
while (firstNode) {
hasMoreBits |= ((firstNode->data >> bit) >> 1) != 0;
int digit = (firstNode->data >> bit) & 1;
partitions[digit]->append(popFirstNode());
}
append(partitions[0]);
append(partitions[1]);
}
}
};
// Demo
int main() {
auto list = new simpleList({4, 9, 1, 2, 6, 8, 3, 7, 5});
list->print();
list->radixSort();
list->print();
}
Example of a base 256 (8 bit) radix sort for linked list using 64 bit unsigned integers for data. The list structure used in the code uses a pointer to pointer for the tail to simplify the code. A base 256 (8 bit, 8 sort passes) is about 8 times as fast as a base 2 (single bit, 64 sort passes) radix sort.
typedef struct NODE_{ // node struct
struct NODE_ * next;
uint64_t data;
}NODE;
typedef struct LIST_{ // list struct
NODE * phead;
NODE ** pptail;
}LIST;
NODE * RadixSort(NODE * plist)
{
LIST alist[256]; // array of lists
NODE *pnode = plist;
uint32_t i, j, k;
size_t x;
for(k = 0; k < 64; k += 8){ // radix sort
for (i = 0; i < 256; i++) { // reset alist
alist[i].phead = 0;
alist[i].pptail = &alist[i].phead;
}
pnode = plist; // split into lists
while(pnode){
x = ((pnode->data) >> k) & 0xff;
*(alist[x].pptail) = pnode;
alist[x].pptail = &(pnode->next);
pnode = pnode->next;
}
// // concatenate lists
for(i = 0; alist[i].phead == 0; i++);
plist = alist[i].phead;
j = i;
for(++i; i < 256; ++i){
if(alist[i].phead == 0)
continue;
*(alist[j].pptail) = alist[i].phead;
j = i;
}
*(alist[j].pptail) = 0;
}
return plist;
};
Related
I'm working on a class project and this piece of code won't let me delete an instance of a class without throwing a breakpoint error.
The class is Node, I'm trying to build a singly linked list for data structures and algorithms. I'll include the whole program, it isn't long, but the code in question that's causing the problem is in deleteMin(), the delete u.
#include <iostream>
using namespace std;
// we create a Node class.
class Node { // inside this class we hold two pieces of information.
int x; // the integer x, which is our data.
Node* next; // and the address of the next node.
public:
Node(int x0) : x(x0), next(NULL) { } // Here I've set up a constructor that sets x equal to the argument
// and defaults the next address to NULL.
bool add(int newValue); // Here follows our three required functions.
int deleteMin();
int size();
void printSSL(); // I also added a printSSL() function so that we can test and see what's going on.
};
//Originally I wanted to put these inside of the Node class, but then you'd end up with a unique head and tail for every Node.
//So instead I've left them outside. If you wanted to create multiple SSList's then you'd want to create an object out of these as well.
Node* head; // The first value in the our SLList.
Node* tail; // The last value in our SLList.
int n; // The number of elements in the list.
// I should mention here that head and tail are set equal to the first value in the SLList in the Main() function below.
// Here follows the actual implementation.
// I chose to try and simplify things by focusing on the add() function.
// If the add function organizes the information, and puts it into the SLList in order,
//then deleteMin() only has to pull the first value.
bool Node::add(int newValue) { // add() is a member function of Node and it takes in the newValue were adding to the list.
Node* u = new Node(newValue); // First thing we do is create a new Node using the argument value x. We pass this into a pointer, u.
if (newValue <= head->x) { // Next, we check to see if the new value is less than the head.
u->next = head; // if it is, then our job is done and we just make this new, smaller value, the new head.
head = u; // we do this by making the initial head equal to the next address in the new Node u.
n++; // Once we have the address saved, we make u into the new head and increment n.
return true; // There's no iteration in this case, so this if statement would be O(1).
}//O(1)
else { // If the new value is greater than the head, then we have to store it further back in the SLList.
Node* y = head; // This was the hardest part of the whole thing... I solved it by creating two Node pointers,
Node* z = head; // Both Node pointers are set equal to head, but this is mostly just to ensure that they aren't empty.
while ((newValue > y->x) && (y != tail)) { // Then I set a while loop that looks at whether the new value is less than the value in the head.
z = y; // The while loop continues, moving through the list of values, setting y equal to the next value,
y = y->next; // and using z to keep track of the former value.
} // The loop exits when we either a) hit the end of the SLList, y == tail, or when the new value is
if (y == tail) { // smaller than the next value, newValue < y->x. When the loop exits we have to deal with these two
y->next = u; // scenarios separately. If we reached the end of our list, then adding the new value is as simple as
tail = u; // setting y->next equal to u, then we make u into the new tail.
} // if we didn't reach the end of the list, then we have to set u inbetween z and y. This was really
else { // the only reason I needed z. I needed to be able to update the address of the previous Node, and
z->next = u; // I also needed to have the address of the next Node, this way I could slip u inbetween the two.
u->next = y; // Worst case scenario, this function runs through the entire SLList and then adds the value at the end.
} // I could have shaved off some time by asking if(newValue > tail->x) then run the z->next=u; and u->next=y; after
n++; // after that, but that throws an error becauset ail is a NULL pointer, which is bull#*#!
return true; // because I'm not dealing the tail->next, all I care about is tail->x which isn't NULL.
}//O(n) // But because this is an SSList and not a DLList I have no way of going to the n-2 element.
}//O(max(1, n)) // When that's done, we just increment n and leave the function.
// Considering that the worst case scenario, when x > tail->x, takes us through the whole SLList.
// I'm going to say that this add function is O(n).
int Node::deleteMin() { // The deleteMin() function starts by checking whether or not the
int x = head->x;
Node* u = head;
head = head->next;
delete u; // I have to figure out what the hells going on right here, why can't I delete this?
return x;
}
int Node::size() {
cout << n + 1 << endl;
return n + 1;
}
void Node::printSSL() {
Node* u = head;
cout << "Head:";
for (int i = 0; i <= n; i++) {
cout << i << ":(" << u->x << ", " << u->next << ") ";
u = u->next;
}
cout << " Tail" << endl;
}
int main()
{
Node one(1);
head = &one;
tail = &one;
one.printSSL();
one.deleteMin();
}
You declared an object of the type Node
Node one(1);
You may not apply the operator delete to a pointer to the object because the object was not allocated dynamically. It has automatic storage duration.
Pay attention to that it is a bad idea when functions depend on global variables. For example you will be unable to define two lists in your program.
What you need is to define a class named something like List the following way
class List
{
private:
Node *head = nullptr, *tail = nullptr;
public:
// special member functions and some other member functions;
void clear();
~List() { clear(); }
};
and to allocate nodes dynamically that will be inserted in the list.
The destructor and the function clear will delete all the allocated nodes in the list.
class Node also should be defined as a nested class of the class List.
For example the function clear can be defined the following way
#include <functional>
//...
void List::clear()
{
while ( head )
{
delete std::exchange( head, head->next );
}
tail = nullptr;
}
#include <iostream>
using namespace std;
class SLList { // SLList is the object that holds the entire list.
public: // The Node class lives inside the SLList class.
struct Node {
int data;
Node* next;
Node(int x0) : data(x0), next(NULL) {}
Node() : data(NULL), next(NULL) {}
};
Node* head;
Node* tail;
int n;
SLList() : n(0) {
Node* initial = new Node();
head = initial;
tail = initial;
cout << "You've created a new SSList" << endl;
}
bool add(int newValue);
int deleteMin();
int size();
void printSSL();
};
bool SLList::add(int newValue) { //
if (n == 0) {
head->data = newValue;
n++;
return true;
}
else {
Node* u = new Node(newValue);
if (newValue <= head->data) { //
u->next = head; //
head = u; //
n++; //
return true; //
}//O(1)
else { //
Node* y = head; //
Node* z = head; //
while ((newValue > y->data) && (y != tail)) { //
z = y; //
y = y->next; //
} //
if (y == tail && newValue > y->data) {
y->next = u; //
tail = u; //
} //
else { //
z->next = u; //
u->next = y; //
} //
n++; //
return true;
}
}//O(n) //
}//O(max(1, n)) //
int SLList::deleteMin() {
int x = head->data;
Node* u = head;
head = head->next;
delete u;
n--;
return x;
}//O(1)
int SLList::size() {
cout << n + 1 << endl;
return n + 1;
}//O(1)
void SLList::printSSL() {
Node* u = head;
cout << n << " Nodes|" << "Head:";
for (int i = 0; i < n; i++) {
cout << i << ":(" << u->data << ", " << u->next << ") ";
u = u->next;
}
cout << " Tail" << endl;
}//O(n)
int main() {
SLList* one = new SLList;
one->printSSL();
one->add(30);
one->printSSL();
one->add(20);
one->printSSL();
for (int i = 0; i < 7; i++) {
int x = rand() % 50;
one->add(x);
one->printSSL();
}
for (int i = 0; i < 9; i++) {
one->deleteMin();
one->printSSL();
}
}
I have to develop a library function for a phonebook which uses lists.
This function has to delete the nth entry from the list.
It is a linked list,and the entries are structs which contain the strings name,srnm,nmbr,addr,the int number and the next pointer.
Every time I call the function,however,VS gives me lot of exceptions and triggered breakpoints,and says I've corrupted the heap.
I have no idea of where I could have made this mistake that corrupts the heap.Please Help.
Here's what I've done so far :
typedef struct list {
char name[20];
char srnm[20];
char nmbr[20];
char addr[20];
unsigned int number;/*Contact index*/
struct list *next;
} entry;
static unsigned int count = 0;
static entry *hol = NULL;/*pointer to the head of the list*/
int delete_contact(unsigned int n) {
int i=0,k=0;
if(n>count) return -1;
hol[n-1].next = hol[n-1].next->next;
for(i=n;i<count;i++) {
hol[i]=hol[i+1];
}
for(i=n;i<count;i++)
hol[i].number = hol[i].number-1; /*Updates the contact index*/
count--; /*Updates the global variable that gives the number of contacts */
return 0;
}
Suggested solution
hol is a pointer, so, hol[n-1] etc. might not refer to a entry struct in memory, consider when n = 0. Either way, this is not how you should access different entries in your list structure.
For a singly-linked list you have to consider 3 cases,
If n = 0 (i.e. the first entry) is being deleted
If the entry to be deleted is somewhere inside the list
If the entry is the last entry in the list.
It is my understanding that number is the index of the list entry and that you've used dynamic memory allocation for the list entries. Furthermore, since you appear to be using the C89 standard (which does not allow loop variable initialization) I have adapted the code below as best as I could to C89, but I do not use that standard myself:
int delete_contact(unsigned int n) {
int i = 0;
int k = 0;
// Check if the index refers to an element not included in the list
if (n > count) { return -1; }
entry* tmp = hol;
if (n == count - 1) {
// Iterate to the last entry
while (tmp->next) {
tmp = tmp->next;
}
free(tmp); // Free the list entry
// Decrement the global counter keeping track of the
// amount of list elements
count--;
// No need to edit the contact indexes
return;
}
entry* remaining_list = hol;
if (n == 0) {
// Free the head of the list
hol = hol->next;
remaining_list = hol;
free(tmp); // tmp points to the head of the list already
} else {
// The list entry is somewhere inside the list
int idx = 0;
// Iterate until tmp points to the n-1:th entry
while (idx < n - 1) {
tmp = tmp->next;
idx++;
}
entry *to_be_freed = tmp->next; // n:th entry
tmp->next = tmp->next->next;
remaining_list = tmp->next;
free(to_be_freed);
}
// Decrement the contact index on all the remaining entries
while (remaining_list) {
remaining_list->number--;
remaining_list = remaining_list->next;
}
// Decrement the global counter keeping track of the
// amount of list elements
count--;
return 0;
}
Tips
You'd be better served by creating a more expressive list interface, possibly one that isn't bound to the values stored inside it. That way you could create a
list_size()
function and remove the global counter.
Here is a little something to get you started:
typedef struct node {
void* value;
struct node* next;
} node;
typedef struct list {
node* head;
node* tail;
size_t len;
} list;
Reference material
Linked list basics
Linked list exercises
I'm having trouble creating a Depth First Search for my program. So far I have a class of edges and a class of regions. I want to store all the connected edges inside one node of my region. I can tell if something is connected by the getKey() function I have already implemented. If two edges have the same key, then they are connected. For the next region, I want to store another set of connected edges inside that region, etc etc. However, I am not fully understanding DFS and I'm having some trouble implementing it. I'm not sure when/where to call DFS again. Any help would be appreciated!
class edge
{
private:
int source, destination, length;
int key;
edge *next;
public:
getKey(){ return key; }
}
class region
{
edge *data;
edge *next;
region() { data = new edge(); next = NULL; }
};
void runDFS(int i, edge **edge, int a)
{
region *head = new region();
aa[i]->visited == true;//mark the first vertex as true
for(int v = 0; v < a; v++)
{
if(tem->edge[i].getKey() == tem->edge[v].getKey()) //if the edges of the vertex have the same root
{
if(head->data == NULL)
{
head->data = aa[i];
head->data->next == NULL;
} //create an edge
if(head->data)
{
head->data->next = aa[i];
head->data->next->next == NULL;
}//if there is already a node connected to ti
}
if(aa[v]->visited == false)
runDFS(v, edge, a); //call the DFS again
} //for loop
}
assuming n is total number of edges, k is final number of regions.
Creating adjacency list for the requisite DFS might be too costly O(n^2) (if k=1 i.e. all edges belong to same region) and hence dfs will cost you O(V+E) i.e. O(n^2) in the worst case.
Otherwise problem is easily solvable in O(n * log(k)) as follows:
Traverse through all edges adding them to the head of corresponding regions (using balanced bst eg. stl-map) [you may use hashing for this too]
traverse through all the regions and connect them in requisite linear fashion
No guaranteed O(n) solution exists for the problem I guess..
I tried to implement a adjacency list creating function.The next pointer of adj_list struct takes you down the adjacency list(there is no relationship between 2 nodes connected by next) and the list pointer is the adjacency list. The node has the address of the adj_list which has its adjacency list.
struct node{
int id;
adj_list* adj;
};
struct adj_list{
adj_list* next;
adj_list* list;
node* n;
adj_list(node& _n){
n = &(_n);
next = NULL;
list = NULL;
}
};
node* add_node(int id,std::queue<int> q , node* root)
{
node* n = new node(id);
adj_list* adj = new adj_list(*n);
n->adj = adj;
if(root == NULL){
return n;
}
std::queue<adj_list*> q1;
while(1){
adj_list* iter = root->adj;
if(q.empty())break;
int k = q.front();
q.pop();
while(iter){
if(iter->n->id == k){
q1.push(iter);
adj_list* temp = iter->list;
iter->list = new adj_list(*n);
break;
}
iter = iter->next;
}
}
adj_list* iter = root->adj;
while(iter->next){
iter = iter->next;
}
iter->next = adj;
while(!q1.empty()){
adj_list* temp = q1.front();
q1.pop();
adj->list = temp;
adj = temp;
}
return root;
}
I'm trying to wrap my head around how to write an algorithm to sort a linked list, but I'm having a hard time coming up with something that will work. What we need to do have a linked list that contains a name in a string, and an int for hours. After displaying the list and the sum of the hours, we then have to sort the list in ascending order by the hours in a queue. I have the list and all it's functioned stored in a class object, as you will see. I cleared the whole function of what I had in hopes of coming up with a fresh idea but nothing is coming to mind. I initially was going to create a second linked list that had the sorted list, but then I began to wonder if it was possible to sort it within the same list. Here is my code as of posting.
#include <iostream>
#include <ctime>
using namespace std;
// OrderedLL class
template<class T>
class OrderedLL
{
private:
struct NODE
{
string sName;
int sHours;
NODE *next;
};
NODE *list;
NODE *rear;
public:
// Constructor
OrderedLL () { list = rear = NULL;}
// Insert item x -------------------------------------
void Insert(string x, int y)
{
NODE *r;
// Create a new node
r = new(NODE); r->sName = x; r->sHours = y;
r->next = NULL;
// Inserts the item into the list
r->next = list;
list = r;
}
// Display the linked list --------------------------
void display()
{ NODE *p = list;
while( p != NULL)
{ cout << p->sName << "/" << p->sHours << "-->"; p = p->next;}
cout << "NULL\n";
}
// Delete x from the linked list --------------------
void DeleteNode(T x)
{
NODE *p = list, *r = list;
while( p->info != x) {r=p; p=p->next; }
if( p == list)
{ // delete the first node
list = p->next; delete(p);
}
else
{ r->next = p->next; delete(p);}
}
// Sort by hours ------------------------------------
void sortHours()
{
NODE *p, *q;
}
// Display the total hours --------------------------
friend T totHours(OrderedLL LL)
{
NODE *p;
int total = 0;
p = LL.list;
while(p != NULL)
{
total += p->sHours;
p = p->next;
}
cout << "Total spending time = " << total << endl;
}
}; // end of OrderedLL class
int main(void)
{
// Declare variables
time_t a;
OrderedLL<int> unsortedLL;
OrderedLL<int> sortedLL;
int inHours;
string inName;
// Displays the current time and date
time(&a);
cout << "Today is " << ctime(&a) << endl;
// Asks the user to enter a name and hours 5 times, inserting each entry
// into the queue
for(int i = 0; i < 5; i++)
{
cout << "Enter name and Time: ";
cin >> inName >> inHours;
unsortedLL.Insert(inName, inHours);
}
// Displays the unsorted list
cout << "\nWaiting List-->";
unsortedLL.display();
totHours(unsortedLL);
// Calls for the function to sort the list into a queue by hours
unsortedLL.sortHours();
unsortedLL.display();
return 0;
} // End of "main"
As always thanks to anyone who can help
Try sorting the linked-list like you are sorting an integer array. Instead of swapping the nodes, swap the contents inside the nodes.
If you don't care about efficiency you can use any sorting algorithm. What's different between linked lists and arrays is that the swap operation, to swap the position of two elements while sorting, will be a lot slower because it has to run through the links of the list.
An O(n²) bubble sort is easy to implement with a linked list since it only swaps an element with its neighbor.
If you care about efficiency you can look into implementing the merge sort algorithm even if it's a little more complicated.
You should insert like this
void Insert(string x, int y)
{
NODE *r;NODE *temp;
// Create a new node
r = new NODE; r->sName = x; r->sHours = y;r->next = NULL;
if(list==null)//check if list is empty
{
list=r;//insert the node r in the list
}
else
{
temp=list;
while(temp->next!=null)temp=temp->next;//reach to the end of the list
temp->next=r;//insert it at the end of the list
}
}
No need of rear pointer..just check if list->next is null,if yes you are at the end
and your sorthour function should be
void sortHours()
{
for(NODE* n=list;n->next!=null;n=n->next)//get each of the node in list 1 by 1 except the last one i.e. n
{
for(NODE* n1=n->next;n1!=null;n1=n1->next)//compare the list n node with all the nodes that follow it i.e.n1
{
if(n->sHours > n1->sHours)//if one of the node is the less than n
{
//swap n and n1
node temp=*n;
n->age=n1->age;
n->name=n1->name;
n1->age=temp.age;
n1->name=temp.name;
}
}
}
}
I have a template class OList that is an ordered linked list (elements are ordered in ascending order). It has a function called void insert(const T & val) that inserts an element into the correct place in the list. For example, If I had an OList of ints with the values { 1,3,5 } and called insert(4), the 4 would be inserted between the 3 and the 5, making OList { 1,3,4,5 }.
Now, what I have works fine when inserting elements into EMPTY OLists. However, when I use the following code:
OList<char> list;
for (int i = 0; i < 3; i++) {
list.insert('C');
list.insert('A');
}
printInfo(list);
printList(list) should output:
List = { A,A,A,C,C,C } Size = 6 Range = A...C
Instead, it outputs:
List = { A,C,C,C,
followed by a runtime error.
I have been messing with this for about 5 hours now, but I don't seem to be making any progress (aside from getting DIFFERENT wrong outputs and errors).
There are three relevant pieces of code: OList's default constructor, operator<<, printInfo(), insert(), and a helper function for insert that finds the node to insert the element. I don't see any reason to provide operator<< nor printInfo() since these seem to work fine elsewhere.
// default constructor
OList() {
size = 0;
headNode = new Node<T>;
lastNode = new Node<T>;
headNode->next = lastNode;
lastNode->next = NULL;
}
void insert(const T & val) {
if ( isEmpty() ) {
lastNode->data = val;
}
else {
Node<T> * pre = headNode;
Node<T> * insertPoint = findInsertPoint(pre, val);
Node<T> * insertNode = new Node<T>;
insertNode->data = val;
insertNode->next = insertPoint;
pre->next = insertNode;
// why is pre equal to headNode?
// I thought I changed that when using it
// with findInsertPoint()
cout << (pre == headNode) << endl;
}
size++;
}
// returns the node AFTER the insertion point
// pre is the node BEFORE the insertion point
Node<T> * findInsertPoint(Node<T> * pre, const T & val) {
Node<T> * current = pre->next;
for (int i = 0; (i < getSize()) && (val > current->data); i++) {
pre = current;
current = current->next;
}
return current;
}
lastNode is simply the last node in the list.
headNode is a "dummy node" that contains no data and is only used as a starting place for the list.
Thanks in advanced. I'm really embarrassed to be asking for homework help on the internet, especially since I'm sure the main problem is my lack of a thorough understanding of pointers.
You are passing the pointer to pre by value into findInsertPoint, so it is copied, and the function changes the copy of pointer, and when the function returns, it is still the old pre, not the pre from inside the function.
If you want to change the pointer, you must pass pointer to the pointer to the function (or reference to pointer).