I'm writing a program doing LSD radix sort with SSN. The program will parse the number into 3 digits and do 3 passes. Each pass I store the number into corresponding array element bucket[]; if there's a duplicate, I create a linked list in that location and store the duplicated one behind the one that's already there. The code breaks when I try to insert in the end of the linked list.
EDIT new error message
class node
{
public:
node(int n, node *p){data=n;next=p;}
int data;
node *next;
};
void genData(int *dta, int n)
{
for(int i=0; i < n; i++)// generate the social security numbers at random
dta[i] = rand()%889 + 111 + 1000*(rand()%889 + 111) + 1000000* (rand()%889 + 111);
}
int radixSort(int *dta, int n, int *out)
{
// the dta array contains the data to be sorted.
// n is the number of data items in the array
// out is the array to put the sorted data
node *bucket[1000]; // declare an array of 1000 linked lists (head pointers)
int count = 0; // use this to count the instructions to graph the big-o
for(int i = 0; i < n; i++)out[i] = dta[i];
for (int pass = 0; pass < 3; pass++)
{
for (int j = 0; j < 1000; j++){
bucket[j] = NULL;
}
delete bucket;
delete[]bucket;
for (int i = 0; i < n; i++){
int index=0;
switch (pass)
{
case 0:
index = out[i] % 1000;
case 1:
index = (out[i]/1000) % 1000;
case 2:
index = out[i] / 1000000;
};
if (bucket[index] = NULL){
bucket[index] = new node(out[i], NULL);
}
else{
node *cur=bucket[index];
while (cur->next!= nullptr){ //****access violation reading location
cur = cur->next;
}
node *ptr = new node(out[i], NULL);
cur->next = ptr;
}
}
int idx = 0;
for (int i = 0; i < 1000; i++){
if (bucket[i] == NULL) continue;
else{
out[idx] = bucket[i]->data;
idx++;
count++;
}
}
}
Theres a number of problems in your code:
In your switch-statement you have lines like index == out[i] % 1000;Those do a comparison and i doubt this is what you want. Assignments use single =
Your initialization for (int j = 0; j < 1000; j++){bucket[j] = NULL;} does not check if theres already a pointer in it - this will cause memory leaks after the first pass. Remember: Every new needs a delete.
And thats what is probably breaking your code: while (cur!= NULL){cur = cur->next;} exits the while-loop once cur is the nullptr - which means trying to dereference it 2 lines later is trying to dereference the nullptr and a bad idea. What you probably want to check in order to get your last element is `while(cur->next != nullptr)
And just as a note: if your compiler supports nullptr its a good idea to use it, even if you might need to enable C++11 via appropriate flags.
Related
vector<minHeap> letters;
letters = countLetters(text);
while (letters.size() >= 2) {
minHeap first = popMin(&letters);
minHeap second = popMin(&letters);
minHeap third('$');
third.count = first.count + second.count;
third.left = &first;
third.right = &second;
letters.push_back(third);
}
I tried to debug the code. The 'first', 'second' and 'third' values are working correctly. My problem is: When I push the 'third' into the vector, in the next round of the loop, the object that we pushed in the last round is changed to the new 'third' and is same with the 'third' in the new round.
For example in the first round X is pushed into the vector, In the next round Y is pushed but the problem is it changes the X to Y too, so we have 2 Ys now. and again in the next round we have 3 Z.
Like it's not creating a copy of the 'third', so when I change it, it changes the previous objects too.
What am I doing wrong? :s
Edit:
minHeap class:
class minHeap {
public:
char letter;
int count = 1;
minHeap* left = NULL;
minHeap* right = NULL;
minHeap(char letter) {
this->letter = letter;
}
};
popMin: (Finds the minimum 'count' in the minHeaps and destroys it, then returns a copy of it)
minHeap popMin(vector<minHeap>* letters) {
int index = 0;
for (size_t i = 0; i < letters->size(); i++) {
if (letters->at(i).count < letters->at(index).count)
index = i;
}
minHeap res = letters->at(index);
letters->erase(letters->begin() + index);
return res;
}
countLetters: (Counts letters and creates a minHeap object for each, increases the 'count' (freq) if it's created before.
vector<minHeap> countLetters(string text) {
vector<minHeap> letters; // Stores all the characters with their count
for (size_t i = 0; i < text.length(); i++) {
bool found = false;
for (size_t j = 0; j < letters.size(); j++) {
if (letters.at(j).letter == text[i]) {
letters.at(j).count++; // Character exists in list, increase its count by one
found = true;
break;
}
}
if (!found) { // Character doesn't exist in list, create it and push it to the list
minHeap letter(text[i]);
letters.push_back(letter);
}
}
return letters;
}
In General: I'm trying to do the huffman coding using minHeap.
You're storing &first and &second, which become invalid pointers when
the current iteration ends. If you dereference them after that, your
program has undefined behaviour. #molbdnilo
So I changed my code to :
vector<minHeap> letters;
letters = countLetters(text);
while (letters.size() >= 2) {
minHeap* first = new minHeap('-');
*first = popMin(&letters);
minHeap* second = new minHeap('-');
*second = popMin(&letters);
minHeap third('$');
third.count = first->count + second->count;
third.left = first;
third.right = second;
letters.push_back(third);
}
And it's fixed. Thanks :)
I have a class called ContactInfo and is structured as written below:
class ContactInfo
{
private:
string contactName;
string contactNumber;
public:
ContactInfo()
{
contactName = "";
contactNumber = "";
}
//setter and getters
};
and I have a function that creates an array of ContactInfo and populates it via user input. After populating the array it would be passed to another function that would sort it, the said function is written as shown below.
void sortListByName(ContactInfo contactList[], int listSize)
{
for(int i = 0; i < listSize; i++)
{
for(int j = i+1; j < listSize+1; j++)
{
if(contactList[i].getContactName() > contactList[j].getContactName())
{
ContactInfo temp = contactList[j];
contactList[i] = contactList[j];
contactList[j] = temp;
}
}
}
}
The main method
int main()
{
...
int n;//array size
ContactInfo *newList = contactList(n);//populates the array.
sortListByName(newList, n);
...
}
The problem is that the program would terminate before the sorting would happen and produce the error:
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_M_construct null not valid
Look at the upper bound of your inner loop. Notice that we can have j equal to the size of the array for the last iteration.
In C++, an array of size N has its elements indexed from 0 to N-1. In your case, you're trying to access an element past the end of the array, and are running into Undefined Behaviour. Ensure your index is within the bounds of the array.
Secondly, you should be using std::vector over raw arrays wherever possible anyways.
Third, the standard library provides the std::sort algorithm for you, which will almost always be faster than the bubble sort that you have implemented.
Your error is made in sort algorithm in the last iteration.
The thing is, that in first for loop variable i goes from 0 to listSize,
and in second for loop variable j goes from i+1 to listSize+1. When variable i reaches listSize-1, variable j will start from i+1 in the second for loop. This means j=listSize, and then when you try to access contactList[j] an error is going to occur because elements of contactList start from index 0 and end with index listSize-1.
void sortListByName(ContactInfo contactList[], int listSize)
{
for(int i = 0; i < listSize; i++) //it should be for(int i=0;i<listSize-1;i++)
{
//here is your mistake. When i = listSize-1 then j=listSize and
// that index is out of range.
for(int j = i+1; j < listSize+1; j++) //it should be for(int j=i+1;j<listSize;j++)
{
if(contactList[i].getContactName() > contactList[j].getContactName())
{
ContactInfo temp = contactList[j];
contactList[i] = contactList[j];
contactList[j] = temp;
}
}
}
}
this is how your code should look like:
void sortListByName(ContactInfo contactList[], int listSize)
{
for(int i = 0; i < listSize-1; i++)
{
for(int j = i+1; j < listSize; j++)
{
if(contactList[i].getContactName()> contactList[j].getContactName())
{
ContactInfo temp = contactList[j];
contactList[i] = contactList[j];
contactList[j] = temp;
}
}
}
Trying to understand the insertion sort algorithm..
My algorithm looks like this currently:
void insertionSort(int *array, int N) {
int value;
int hole;
int *array2;
for (int i = 1; i < N - 1; i++) {
value = array[i]; //next item to be inserted in array 2
hole = i;
while (hole > 0 && array[hole - 1] > value) {
array[hole] = array[hole - 1];
hole = hole - 1;
}
array[hole] = value;
}
}
My algorithm works for sorting arrays, however I now need to change it so that I build up a new sorted array (array2) one element at a time, rather than just working with the original array.
Is there a simple way to implement this given my completed algorithm?
Thanks.
You can use the following method:
int *array2 = calloc(N, sizeof(int));
for(var index = 0; index < N; index++)
{
array2[index] = array[index];
}
and after that use array2 instead of array
then just change the prototype of your function to int *insertionSort
All remaining is to return array2 at the end of task
But be aware of memory leak: https://en.wikipedia.org/wiki/Memory_leak
I am new to C++ programming and I would like to get all the possible combinations of a one-dimensional array with 5 elements and without numbers repeating for example it starts with 00001, 00002, 00003, ... ,99999.
int count(){
while (i<100000){ //loop to go thru all possible combinations
//std::cout<<i<<"\t";
if (i>=10000){
num(i);
print();
}
i++;
}
}
void num (int i){ /* method to sort all the number to the array for i */
takeNumbersFromUser=i;
for( n=0;n<arraySize;n++){
if (control==0){
ar[n]=takeNumbersFromUser % 10;
}
else if (control==1){
temp= takeNumbersFromUser % 100;
ar[n]=temp/10;
}
else if (control==2){
temp = takeNumbersFromUser % 1000;
ar[n] = temp/100;
}
else if (control==3){
temp = takeNumbersFromUser % 10000;
ar[n] = temp/1000;
}
else if (control==4){
temp = takeNumbersFromUser % 100000;
ar[n] = temp/10000;
}
control++;
}
}
void print(){ //print out
std::cout<<"\n\n\tyou entered "<<takeNumbersFromUser<<"\n\n";
for (n=5;n>=0;n--){
std::cout<<ar[n]<<"\t";
}
}
}
Thank you.
Something like?
// Size of parent array (10^length)
int size = 100000;
// Length of number
int length = 5;
// Two dimensional array to hold the numbers
int** matrix = new int*[size];
// Create all elements in the array
for(int i=0;i<size;i++) {
matrix[i] = new int[length];
// Temporary variable to "play" with 'i'
int temp = i;
for(int j=length-1;j>=0;j--) {
matrix[i][j] = temp%10;
temp /= 10;
}
}
I believe this is very simple, and does not require further explanation.
If it does, please ask and I will provide
EDIT:
As suggested, you can replace the int* array with:
new vector<int>[size]
Then in the for j loop, there is no need to create a new array, and you can just use: matrix[i].push_back(temp%10)
And finally, to print this, you can do a new for i loop, going over the vectors array, and inside to have a foreach loop, something like:
for(int n : v)
std::cout << n << " ";
You can deffinetly should be able to manage from here.
How can I make an inset method that will add a number into the array in the correct order?
void addElement(int table[], int element, int length) {
int x = 0;
int temporary=0;
cout<<length<<endl;
if(length == 1) {
table[0] = element;
}
else {
if(length == 2) {
if (table[0] > element) {
int temp = table[0];
table[0] = element;
table[1] = temp;
}
else {
table[1] = element;
}
}
else {
for(int i = 0; i< length && x == 0; i++) {
if(element<table[i] && element>=table[i-1]) {
for(int y = i; y<length; y++) {
temporary = table[y+2];
int temp = table[y];
table[y] = element;
table[y+1] = table
}
}
}
}
}
}
This is as far as I have gotten. In my main class I have worked it out so that array is increased by 1. So there is one open space at the end of the array for everything to be pushed back by 1.
You can scan the array from back to front, moving values up until you find the correct insertion point.
void addElement(int *table, int element, int length)
{
int i = length - 1;
for (; i > 0 && table[i-1] > element; --i)
{
table[i] = table[i-1];
}
table[i] = element;
}
Write a shiftElements function, write a findIndexOfFirstGreaterThan function, then in addElement - find the index, if -1 then put in last slot, else shift elements using index, then a[index]=elem;
Draw yourself an example, then work out a list of very simple steps required to do what you want.
Then write code that does those steps.
Im not sure if this is what your looking for, but I think you want something that adds an element depending on its integer value. Also, I do not have access to a compiler at this moment so there might be a couple of errors. The code below is just written to give you a brief idea of what you could do, but probably not a perfect solution to your problem.
int addElement (int element, int array [], int length)
{
vector <int> vectorOfInts; //vector to store current order of ints
vector <int> vectorOfArrangedInts; //vector to store arranged order
for (int counter = 0; counter < length; counter ++) //loop to fill the array with values
{
vectorOfInts.push_back (array [counter]);
}
for (int counter = 0; counter < vectorOfInts.length(); counter ++) //loop through all elements
{
int temp = 0; //stores temp value of biggest number found at a specific moment
int elementIndex; //stores indexes
for (int counterTwo = 0; counterTwo < vectorOfInts.length(); counterTwo ++) //loop through all elements to find the biggest array
{
if (vectorOfInts.at (counterTwo) >= temp) //if value is bigger than current biggest number
{
temp = vectorOfInts.at (counterTwo); //change temp value
elementIndex = counterTwo; //remember index
}
}
vectorOfArrangedInts.push_back (vectorOfInts.at(elementIndex)); //add the biggest number to the arranged values
vectorOfInts.erase (vectorOfInts.begin() + elementIndex); //remove the biggest element
}