How can I traverse a Huffman Tree (via code) and print out the encodings for each letter? - c++

I'd like to start with what I know about heaps and Huffman code.
For this project, we use a minimum heap. The top part of the upside-down tree (or root) holds the minimum element. Whenever something is added to the array, everything gets moved, so the root is always the minimum value element. Whenever an element is deleted, everything gets reconfigured with the top element holding the minimum once again. In class, we went over a (template) class called MaxHeap, which I converted into MinHeap without the template stuff.
My professor went over Huffman encoding, but I understood it best using this visual tool:
https://people.ok.ubc.ca/ylucet/DS/Huffman.html
The idea is to use a minimum heap as follows:
1. Delete two nodes
2. Create a new node with the deleted nodes as children. The frequency of this node is the summation of the two children frequencies.
3. Add this new node to the minimum heap
This process repeats until there is one node left in the heap (the root). Next, we find the encodings for each letter. To do this, travel down the tree with left movement being 0 and right movement being 1. Traveling right twice then left once would give 110 for the letter 'c' in my tree (image link can be found towards the bottom of my post).
Everything was going mostly fine until I needed to traverse from the root. I had no idea how to do this via code, so I tried googling the answers and found these two websites:
https://www.geeksforgeeks.org/huffman-coding-greedy-algo-3/
https://www.programiz.com/dsa/huffman-coding
I copied their function printCodes() into my code, but I didn't get see it work.
When I try manually going down the tree, I get two things. For example, I tried traveling left down the root and using cout to see the values. I expected to see 40, !, e, d; but when I tried I was getting gibberish number and characters (greek letters like theta, sigma, etc). It gets really weird because on line 207, yourRoot->left->freq gives me 40, but the same thing on the line 208 of code gives me a large number. When I traveled right, I got: Exception thrown: read access violation. yourRoot->right->right->letter was 0xCCCCCCCC.
To reiterate cout << yourRoot->left->freq << endl; will give me 40 the first time I call it, but the second time I get a random number. I expected the same output twice in a row. Am I supposed to keep a pointer or pointer-to-pointer to the address of yourRoot or something?
Another problem is in createHuffmanTree(), if I put return root; outside the while loop I get this error and the code doesn't run at all:
potentially uninitialized local pointer variable 'root' used
Both of these things were odd problems and I assume it has to do with the way I'm using & and * symbols. I tried using something like this:
MinHeap yourHeap = MinHeap(6);
node *item = newNode(30, 'f');
yourHeap.Insert(*item);
item = newNode(20, 'e');
yourHeap.Insert(*item);
item = newNode(20, 'd');
yourHeap.Insert(*item);
item = newNode(15, 'c');
yourHeap.Insert(*item);
item = newNode(10, 'b');
yourHeap.Insert(*item);
item = newNode(5, 'a');
yourHeap.Insert(*item);
delete item;
This works the same as the yourList[] code I have in main(), but I figured "keep it simple stupid" and avoid using pointers since I clearly have some issues with them.
I uploaded an output without any error causing code and a drawing of what I expect my tree to look like with the values I want to use (https://imgur.com/a/Vpx7Eif). If the link doesn't work, please let me know so I can fix it.
The code I have thus far is:
#include <iostream>
using namespace std;
#define MAX_TREE_HEIGHT 20
//exception is thrown if wrong input
class NoMem
{
public:
NoMem() { cout << "Heap is full\n"; }
};
class OutOfBounds
{
public:
OutOfBounds() { cout << "Heap is empty\n"; }
};
struct node
{
int freq;
char letter;
struct node *left, *right;
};
// initialize node with frequency and letter
node* newNode(int freq, char letter)
{
node *temp = new node;
temp->freq = freq;
temp->letter = letter;
temp->left = nullptr;
temp->right = nullptr;
return temp;
}
// initialize node using two nodes as children
node* newNode(node& a, node& b)
{
node *temp = new node;
temp->freq = a.freq + b.freq;
temp->letter = '!';
temp->left = &a;
temp->right = &b;
return temp;
}
class MinHeap {
public:
MinHeap(int MSize)
{
MaxSize = MSize;
heap = new node[MaxSize + 1];
Size = 0;
}
~MinHeap() { delete[] heap; }
MinHeap& Insert(node& x);
MinHeap& Delete(node& x);
void Display();
int Size;
private:
int MaxSize;
node *heap;
};
MinHeap& MinHeap::Insert(node& x)
{
if (Size == MaxSize) throw NoMem();
else
{
printf("Inserting '%c' with frequency of %d. ", x.letter, x.freq);
int i = ++Size;
while (i != 1 && x.freq < heap[i / 2].freq)
{
heap[i] = heap[i / 2];
i /= 2;
}
heap[i] = x;
Display();
return *this;
}
}
MinHeap& MinHeap::Delete(node& x)
{
if (Size == 0) throw OutOfBounds();
x.freq = heap[1].freq; // root has the smallest key
x.letter = heap[1].letter;
printf("Deleting '%c' with frequency of %d. ", x.letter, x.freq);
node y = heap[Size--]; // last element
int vacant = 1;
int child = 2; //make child = left child
while (child <= Size)
{
if (child < Size && heap[child].freq > heap[child + 1].freq) ++child;
// right child < left child
if (y.freq <= heap[child].freq) break;
heap[vacant] = heap[child]; // move smaller child
vacant = child; // new vacant
child = child * 2; // new child of vacant
}
heap[vacant] = y;
Display();
return *this;
}
void MinHeap::Display()
{
printf("Your heap contains: ");
for (int i = 1; i <= Size; i++)
printf("'%c' = %d, ", heap[i].letter, heap[i].freq);
printf("\n");
}
node* createHuffmanTree(MinHeap& yourHeap)
{
cout << "--- Creating Huffman Tree ---\n";
node left, right, *root;
while (yourHeap.Size > 1)
{
yourHeap.Delete(left);
yourHeap.Delete(right);
root = newNode(left, right);
cout << "-> New Node: freq = " << root->freq << ", letter = " << root->letter << ", left: " << root->left->letter << ", right: " << root->right->letter << endl;
yourHeap.Insert(*root);
if (yourHeap.Size < 2)
{
return root;
}
}
//return root; // potentially uninitialized local pointer variable 'root' used
}
void outputHuffmanCode(node* root, int arr[], int top)
{
// left movement is 0
if (root->left)
{
arr[top] = 0;
outputHuffmanCode(root->left, arr, top + 1);
}
// right movement is 1
if (root->right)
{
arr[top] = 1;
outputHuffmanCode(root->right, arr, top + 1);
}
// if reached leaf node, must print character as well
if (!(root->left) && !(root->right))
{
cout << "'" << root->letter << "' = ";
for (int i = 0; i < top; ++i)
cout << arr[i];
cout << endl;
}
}
int main()
{
node yourList[6];
yourList[0].freq = 5;
yourList[0].letter = 'a';
yourList[1].freq = 10;
yourList[1].letter = 'b';
yourList[2].freq = 15;
yourList[2].letter = 'c';
yourList[3].freq = 20;
yourList[3].letter = 'd';
yourList[4].freq = 20;
yourList[4].letter = 'e';
yourList[5].freq = 30;
yourList[5].letter = 'f';
cout << "Here is your list: ";
for (int i = 0; i < 6; i++)
{
cout << "'" << yourList[i].letter << "' = " << yourList[i].freq;
if (i < 5) cout << ", ";
} cout << endl;
MinHeap yourHeap(6);
yourHeap.Insert(yourList[5]);
yourHeap.Insert(yourList[4]);
yourHeap.Insert(yourList[3]);
yourHeap.Insert(yourList[2]);
yourHeap.Insert(yourList[1]);
yourHeap.Insert(yourList[0]);
/*
MinHeap yourHeap = MinHeap(6);
node *item = newNode(30, 'f');
yourHeap.Insert(*item);
item = newNode(20, 'e');
yourHeap.Insert(*item);
item = newNode(20, 'd');
yourHeap.Insert(*item);
item = newNode(15, 'c');
yourHeap.Insert(*item);
item = newNode(10, 'b');
yourHeap.Insert(*item);
item = newNode(5, 'a');
yourHeap.Insert(*item);
delete item;
*/
node *yourRoot = newNode(0, NULL);
yourRoot = createHuffmanTree(yourHeap);
// same cout twice in a row, different results
//cout << yourRoot->left->freq << endl;
//cout << yourRoot->left->freq << endl;
cout << "L0 Root: freq = " << yourRoot->freq << ", letter = " << yourRoot->letter << ", left freq: " << yourRoot->left->freq << ", right freq: " << yourRoot->right->freq << endl;
cout << "L11 Left: freq = " << yourRoot->left->freq << ", letter = " << yourRoot->left->letter << ", left: " << yourRoot->left->left->letter << ", right: " << yourRoot->left->right->letter << endl;
//cout << "R11 Left: freq = " << yourRoot->right->freq << ", letter = " << yourRoot->right->letter << ", left: \n";
//<< yourRoot->right->left->letter << ", right: " << yourRoot->right->right->letter << endl;
//int arr[MAX_TREE_HEIGHT], top = 0;
//outputHuffmanCode(yourRoot, arr, top);
system("pause");
return 0;
}
I'd like to thank whoever reads and replies to this post in advance. I think I've given as much information as I could. If I did anything that's against community rules, please let me know so I can fix my mistake(s).

In your createHuffmanTree Function, you create the node's left and right...
with root = newNode(left, right); you let the left/right member of your struct point to the address of the (temporary) node you've created in createHuffmanTree (that means in
node* newNode(node& a, node& b)
the address of a and b is always the same..
and the node goes out of scope after leaving the createHuffmanTree function - i think this causes your problem. You know what I mean?

Related

if user enter 5 then display the last 5 elements of linked list vise versa

i am stuck in my uni assignment....
i have an linked list of 20 elements, i have to take the value from user and if user enter 5 then print the last 5 elements of linked list
void traverse(List list) {
Node *savedCurrentNode = list.currentNode;
list.currentNode = list.headNode;
for(int i = 1; list.next() == true; i++)
{
std::cout << "Element " << i << " " << list.get() << endl;
}
list.currentNode = savedCurrentNode;
}
im trying this but this method prints all the elements of my linked list
For what little code you have, a review:
// Why are you passing the list by value? That is wasteful.
void traverse(List list) {
// I don't see you taking a value anywhere; surely you know how to do that
// What is happening here? Can't you just assign the head to something
// directly?
Node *savedCurrentNode = list.currentNode;
list.currentNode = list.headNode;
// Like you said, this traverses the entire list, it's also poorly
// formed. You literally don't need i.
// for (; list.next(); /* However your list increments here */)
for(int i = 1; list.next() == true; i++)
{
std::cout << "Element " << i << " " << list.get() << endl;
}
// What is the purpose of this?
list.currentNode = savedCurrentNode;
}
For someone who is writing a linked list, this code seems to be fundamentally flawed. My expectation of someone tackling a linked list is that they are about to stop being a beginner, but I'm not seeing that here in the code and what structure of the list class is implied. The list class is weird to say the least.
And just to be clear, my expectation stems from where I place the linked list assignment in my curriculum. It's also more idiomatic than this list.
With that out of the way, this task is trivial if you took the time to think the project through. Most students skip the planning step and create unnecessary headaches for themselves.
Knowing that you would need the total size of the list, why not just make it member data? Any function that adds to the list will increment the value accordingly. And any function that subtracts from the list will decrement accordingly. That way you always know the size of the list at all times.
Knowing the size of the list is most of the battle. You then need to do the arithmetic necessary to advance in the list to satisfy your requirement. And now you can print.
#include <iostream>
class SList {
public:
SList() = default;
//
// Rule of 5 intentionally left out
//
void push_front(int val) {
m_head = new Node{val, m_head};
++m_size; // The magic happens here
}
std::size_t size() const { return m_size; }
void traverse_last(int numElements, std::ostream& sout = std::cout) const {
int placement = m_size;
Node* walker = m_head;
// Move our walker node the appropriate amount of steps
while (walker && placement > numElements) {
walker = walker->next;
--placement;
}
// Now that we're in position, we can print
while (walker) {
sout << walker->data << ' ';
walker = walker->next;
}
sout << '\n';
}
private:
struct Node {
int data;
Node* next = nullptr;
};
Node* m_head = nullptr;
std::size_t m_size = 0ULL;
};
int main() {
SList test;
for (int i = 5; i > 0; --i) {
test.push_front(i);
}
std::cout << "Size: " << test.size() << '\n';
for (int i = 1; i <= 5; ++i) {
test.traverse_last(i);
}
test.traverse_last(10);
}
Output:
❯ ./a.out
Size: 5
5
4 5
3 4 5
2 3 4 5
1 2 3 4 5
1 2 3 4 5
void traverse(List list, int printFrom)
{
Node *savedCurrentNode = list.currentNode;
list.currentNode = list.headNode;
for(int i=1; list.next(); i++)
{
if(i > printFrom)
{
cout << "Element " << (i - printFrom) << " " << list.get() << endl;
}
}
list.currentNode = savedCurrentNode;
}
solved my prblem by this there printFrom is a variable whose value is number of elemenets that skipped like if my linked list have size of 20 and user want to see last 5 then printFrom stores 15 and skipped 15 values and print last 5

Display() resets the entire array C++

I tried creating a hash map storing its inputs as linked list nodes using separated chaining. The first display function gives a desirable output, but the next one resets the entire array to empty nullptr. I used the same class object so shouldn't it give the same result each time? Was it because of the destructor somehow? I thought it may be because I inserted a new item so I deleted it and the same thing still persists. My only suspect is the display() function but please point out if the problem comes from somewhere else.
Sorry if the post is so long, I want to make sure everyone can see the entire code to spot the problem.
#include <iostream>
#include <string>
#include "C:\Users\admin\source\repos\hash-library-master\sha3.cpp"
using namespace std;
const int TABLE_SIZE = 11;
struct HashNode
{
string key;
string value;
HashNode* next;
};
class HashMap {
private:
HashNode **table;
public:
//each element of table will be a root pointer to their respective chain
HashMap() {
table = new HashNode*[TABLE_SIZE];
for (int i = 0; i < TABLE_SIZE; i++)
{
table[i] = nullptr;
}
}
//hashing algorithm using SHA3 (courtesy of Stephan Brumme)
string hashFunc(string input)
{
string key;
SHA3 sha3;
key = sha3(input);
return key;
}
//insert new node
void insert(string key, string value)
{
//using hashing function to calculate hash index from string variable key
int hash = 0;
for (int a = 0; a < key.length(); ++a)
hash += key[a];
hash = hash % TABLE_SIZE;
//create new node to store data
HashNode* newNode = new HashNode;
newNode->value = value;
newNode->key = key;
newNode->next = nullptr;
//check and insert new node to front of line
if (table[hash] == nullptr)
table[hash] = newNode;
else
{
newNode->next = table[hash]->next;
table[hash]->next = newNode;
}
}
void display()
{
for (int i = 0; i < TABLE_SIZE; ++i)
{
if (table[i] == nullptr)
cout << i << " NULL" << endl;
else
{
while (table[i] != nullptr)
{
cout << i << " " << table[i]->value << "; ";
table[i] = table[i]->next;
if (table[i] == nullptr)
cout << "(end of chain)" << endl;
}
}
}
}
~HashMap() {
for (int i = 0; i < TABLE_SIZE; i++)
if (table[i] != NULL)
delete table[i];
delete[] table;
}
};
Driver
#include <iostream>
#include <string>
#include "hashMap.h"
using namespace std;
int main()
{
HashMap obj;
//test insert
obj.insert("5", "3100 Main St, Houston TX ");
obj.insert("5", "2200 Hayes Rd, Austin TX");
obj.insert("226", "1775 West Airport St, San Antonio TX");
obj.insert("273", "3322 Walnut Bend, Houston TX");
obj.insert("491", "5778 Alabama, Waco TX");
obj.insert("94", "3333 New St, Paris TX");
obj.display(); //resolved
cout << endl << endl;
//testing new hashing algorithm
string input, key;
cout << "Please enter any new address you want to store: ";
cin >> input;
key = obj.hashFunc(input); //create hash key
obj.insert(key, input);
obj.display(); //resets the array somehow
return 0;
}
Output
0 1775 West Airport St, San Antonio TX; (end of chain)
1 NULL
2 3322 Walnut Bend, Houston TX; (end of chain)
3 NULL
4 5778 Alabama, Waco TX; (end of chain)
5 NULL
6 NULL
7 NULL
8 NULL
9 3100 Main St, Houston TX ; 9 2200 Hayes Rd, Austin TX; (end of chain)
10 3333 New St, Paris TX; (end of chain)
//where display() resets
Please enter any new address you want to store: ewrewrw
0 NULL
1 ewrewrw; (end of chain)
2 NULL
3 NULL
4 NULL
5 NULL
6 NULL
7 NULL
8 NULL
9 NULL
10 NULL
Make all member functions that are not supposed to change the object itself const. This ensures that the function can be used when the object is used in a const context and will also enable the compiler to help you if you make a mistake. It will give you compilation errors if you try modifying the object in the function and will therefore complain about the line table[i] = table[i]->next; where you make changes to the object in your current code.
So start by making the function const and fix the errors. With the fixes in place it could look something like this:
void display() const // const added
{
for (int i = 0; i < TABLE_SIZE; ++i)
{
if (table[i] == nullptr)
cout << i << " NULL" << endl;
else
{
// using a temporary pointer, ptr, to go through the list
for(HashNode* ptr = table[i]; ptr != nullptr; ptr = ptr->next)
{
cout << i << " " << ptr->value << "; ";
}
cout << "(end of chain)" << endl;
}
}
}
Your display function is setting all elements of table to nullptr by looping until they become nullptr.
You should use another pointer variable for iterating to avoid this destruction.
void display()
{
for (int i = 0; i < TABLE_SIZE; ++i)
{
if (table[i] == nullptr)
cout << i << " NULL" << endl;
else
{
HashNode *p = table[i]; // another pointer variable for iterating
while (p != nullptr)
{
cout << i << " " << p->value << "; ";
p = p->next;
if (p == nullptr)
cout << "(end of chain)" << endl;
}
}
}
}

C++ access an element of struct array in a struct

This thing has been driving me crazy for a while now.
I need to create and traverse (post order) a general tree where each node (a structure) is added by the user via console.
I am NOT allowed to use STL.
The user specifies how many nodes will be added, and how many 'child' nodes it can hold (number) and the name of the node (string).
Example input:
5
1 A
2 B
1 C
1 D
3 E
The above means that 5 nodes will be added. The first one (A) can accept one 'child' node, (B) can accept 2 such nodes and (C) can accept 1 etc.
The newly added nodes have to always be added to the 'highest' possible node from the top (if it still can accept a new 'child' node, if not possible you go to the next one).
The idea is to create an array (I know how many nodes will be added in total) and put those nodes specified by the user there and 'link' them accordingly using array of pointers inside of a structure.
The output of given example should be: E C D B A
I have written the whole thing as follows but I am unable to traverse the tree:
structure:
struct node {
string name = "";
int noChildrenAdded = 0;
int possibleNoChildren = 0;
int childrenFreeSlots = 0;
node* children = nullptr;
node* father = nullptr;
};
traverse function that's not working
void traverse(node* father)
{
cout << father->name << endl;
if (father == nullptr) {
return;
}
for (int i = 0; i < father->possibleNoChildren; i++) {
if (&father->children[i] == nullptr) {
continue;
}
traverse(&father->children[i]);
}
cout << father->name << "\n";
}
main
int main() {
int n = 0;
short g = 0;
string name;
cin >> n;
node* tree = new node[n];
node* tmp = nullptr;
//adding children to tree array
for (int i = 0; i < n; i++) {
cin >> g >> name;
tree[i].possibleNoChildren = tree[i].childrenFreeSlots = g;
tree[i].name = name;
tree[i].noChildrenAdded = 0;
tree[i].children = new node[1];
}
// making connections between nodes
for (int son = 1; son < n; son++) {
for (int father = 0; father < son; father++) {
if (tree[father].childrenFreeSlots > 0) {
//resizing array
if (tree[father].noChildrenAdded == 0) {
tree[father].children[0] = tree[son];
}
else {
int added = tree[father].noChildrenAdded;
tmp = new node[added + 1];
for (int i = 0; i < added; i++) {
tmp[i] = tree[father].children[i];
}
delete[] tree[father].children;
tree[father].children = nullptr;
tree[father].children = tmp;
tree[father].children[added] = tree[son];
tmp = nullptr;
}
tree[father].noChildrenAdded++;
tree[father].childrenFreeSlots -= 1;
break;
}
}
}
//this is how it should be
cout << "Father: " << tree[1].name << "\tchildren added: " << tree[1].noChildrenAdded << endl;
//tree[0].children[0] is holding pointer to drzewo[1] so the below should give me the same answer as above.
//this is giving me wrong answer
node* ptr = &tree[0].children[0];
cout << "Father: " << ptr->name << "\tchildren added: " << ptr->noChildrenAdded << endl;
//traverse(&tree[0]);
delete[] tree;
}
THE PROBLEMS
I am unable to access details of a structure (for example noChildrenAdded) - I am getting zero, despite the fact that noChildrenAdded is populated. When I access it via tree array I am getting the correct number but when I do it via pointer inside of a struct I am getting 0.
Example:
This is correct: cout << "Father: " << tree[1].name << "\tchildren added: " << tree[1].noChildrenAdded << endl;
But this is not (despite both should be giving the same number/answer):
//tree[0].children[0] is holding pointer to tree[1] so the below should give me the same answer as above.
//this is giving me wrong answer
node* ptr = &tree[0].children[0];
cout << "Father: " << ptr->name << "\tchildren added: " << ptr->noChildrenAdded << endl;
I expect I have messed up assigning children to the *children array inside of a struct. The name seems to be accessible fine but not the noChildren.
Both should be giving the same answer but they are not:
enter image description here
Any help would be greatly appreciated!
PS: when I use this code with static array of children everything is ok, traversal works fine but when I get a dynamic array it's broken. Static array alas won't do as it taking too much memory and takes way too long so my program fails the requirements.
Just as #igor-tandetnik suggested, using an array of node* pointers solved the problem. In my case solution was to use node** children not node *children.

Depth first search (C++)

I've created a class that contains a vector of Linked Lists. Each Linked List represents a vertice in my graph. The Nodes connected to my linked lists are considered the edges between these vertices. I'm trying to create a DFS function for my graph, but am having trouble with setting the colors of my vertices. I realize there are a lot of problems with my code, but i'm trying to solve one in particular. My DFSit() function ends up in an infinite loop because the color attribute for my list isn't actually getting set to "gray". Any idea why this would be?
void Graph::DFS()
{
int i = 0;
while (i != myvector.size())
{
DFSit(myvector[i], myvector[i].val);
myvector[i].color = "black";
i++;
}
}
void Graph::DFSit(AdjList x, int root)
{
if (x.color == "white")
{
cout << "tree edge ( " << root << "," << x.val << ") " << endl;
}
if (x.color == "gray")
{
cout << "Back Edge ( " << root << "," << x.val << ") " << endl;
return;
}
x.color = "gray";
AdjNode *temp = new AdjNode();
temp = x.front;
int i = 0;
int value;
while (temp != NULL)
{
value = temp->getValue();
while (i != myvector.size())
{
if (value == myvector[i].val)
{
DFSit(myvector[i], root);
}
i++;
}
temp = temp->next;
}
}
Normaly, the proper implementation of the DFS rutine is made with a stack, but this could work also.
I think that you are coloring the node AdjList x and this coloring is not save because you are passing it by val and not by ref.
try changing void Graph::DFSit(AdjList x, int root) into void Graph::DFSit(AdjList& x, int root)

getting mergesort to work on linked-list?

Apologies if this is a silly / simple question.. but I'm very lost. I'm having trouble getting this program to run. I've written this program to read in 2 values, the first being a number of elements in a linked list, and the second to be the maximum random value that can be put into each element.
It should then use the merge sort algorithm included to sort and reprint the sorted list.
Ok, so I'm getting errors like:
base operand of `->' has non-pointer type `LIST'
and
request for member `element' in `conductor', which is of non-aggregate type `LIST *'
...(and a few others).
Yes this is for a class.. I've written the program but I'm not sure what I've done wrong here or why I'm getting errors? Any help is appreciated! Thank you
#include <cstdlib>
#include <iostream>
#include <math.h>
#include <sys/time.h>
using namespace std;
typedef struct LIST {
int element;
LIST *next;
};
LIST split(LIST list)
{
LIST pSecondCell;
if (list == NULL)
return NULL;
else if (list.next == NULL)
return NULL;
else {
pSecondCell = list.next;
list.next = pSecondCell.next;
pSecondCell.next = split(pSecondCell->next);
return pSecondCell;
}
}
LIST merge(LIST list1, LIST list2)
{
if (list1 == NULL)
return list2;
else if (list2 == NULL)
return list1;
else if (list1.element <= list2.element) {
list1.next = merge(list1.next, list2);
return list1;
} else {
list2.next = merge(list1, list2.next);
}
}
LIST MergeSort(LIST list)
{
LIST SecondList;
if (list == NULL)
return NULL;
else if (list.next == NULL)
return list;
else {
SecondList = split(list);
return merge(MergeSort(list), MergeSort(SecondList));
}
}
int main(int argCount, char *argVal[])
{
int i, number, max;
struct timeval time1;
struct timeval time2;
//check for correct number of arguments
if (argCount != 3) {
cout << "Incorrect number of arguments" << endl;
return 0;
}
// initialize read in n and max values
number = atoi(argVal[1]);
max = atoi(argVal[2]);
// create list and fill with random numbers
LIST *conductor;
LIST *root = new LIST;
conductor = root;
for (i = 0; i < number; i++) {
conductor.element = rand() % max;
conductor.next = new LIST;
conductor = conductor.next;
}
// time how long it takes to sort array using mergeSort
gettimeofday(&time1, NULL);
mergeSort(root);
gettimeofday(&time2, NULL);
// print name, sorted array, and running time
cout << "Heather Wilson" << endl;
conductor = root;
for (i = 0; i < number - 2; i++) {
cout << conductor.element << ", ";
conductor = conductor.next;
}
double micro1 = time1.tv_sec * 1000000 + time1.tv_usec;
double micro2 = time2.tv_sec * 1000000 + time2.tv_usec;
cout << conductor.element << endl;
cout << "Running time: " << micro2 - micro1 << " microseconds" << endl;
return 0;
}
For base operand of->' has non-pointer type LIST'
Replace the -> with a .. You want to access a member of a local LIST, not a member of a pointed at object.
request for memberelement' in conductor', which is of non-aggregate type LIST *
This is the opposite. Replace the . with a ->. You want to access a member of the pointed at LIST, not a member of the pointer.
For clarification, I didn't read the code. There's too much of it. But those are the usual ways to address those specific errors. parapura seems to have actually read the code.
First: you should never have let the code grow this big with so many errors. You should start small and simple, then build up, testing at every stage, and never add to code that doesn't work.
Here's a stripped-down beginning of your code, with some bugs fixed:
#include <iostream>
using namespace std;
typedef struct LIST{
int element;
LIST *next;
};
int main(){
int i, number, max;
number = 5;
max = 100;
// create list and fill with random numbers
LIST *conductor;
LIST *root = new LIST;
conductor = root;
for(i=0; i<number; i++){
conductor->element = rand() % max;
cout << "element " << i << " is " << conductor->element << endl;
conductor->next = new LIST;
conductor = conductor->next;
}
conductor = root; // Forgot this, didn't you!
for(i=0; i<number-2;i++){
cout << conductor->element << ", ";
conductor = conductor->next;
}
return 0;
}
Take a look at this, verify that it works, make sure you understand the changes I made, then you can take a crack at implementing your split, merge and MergeSort functions and the I/O (one at a time, and testing at every stage, naturally).
I think all the places you are passing
LIST merge ( LIST list1 , LIST list2 )
it should be
LIST* merge ( LIST* list1 , LIST* list2 )