Ducksauce88
Ducksauce88

Reputation: 650

Array of Linked Lists C++

So I thought I understood how to implement an array of pointers but my compiler says otherwise =(. Any help would be appreciated, I feel like I'm close but am missing something crucial.

1.) I have a struct called node declared:.

struct node {

int num;

node *next;

}

2.) I've declared a pointer to an array of pointers like so:

node **arrayOfPointers;

3.) I've then dynamically created the array of pointers by doing this:

arrayOfPointers = new node*[arraySize];

My understanding is at this point, arrayOfPointers is now pointing to an array of x node type, with x being = to arraySize.

4.) But when I want to access the fifth element in arrayOfPointers to check if its next pointer is null, I'm getting a segmentation fault error. Using this:

if (arrayOfPointers[5]->next == NULL)

{

cout << "I'm null" << endl;

}

Does anyone know why this is happening? I was able to assign a value to num by doing: arrayOfPointers[5]->num = 77;

But I'm confused as to why checking the pointer in the struct is causing an error. Also, while we're at it, what would be the proper protoype for passing in arrayOfPointers into a function? Is it still (node **arrayOfPointers) or is it some other thing like (node * &arrayOfPointers)?

Thanks in advance for any tips or pointers (haha) you may have!

Full code (Updated):

 /*
* Functions related to separate chain hashing
*/

struct chainNode
{
    int value;
    chainNode *next;
};

chainNode* CreateNewChainNode (int keyValue)
{
    chainNode *newNode;

    newNode = new (nothrow) chainNode;

    newNode->value = keyValue;
    newNode->next = NULL;

    return newNode;
}


void InitDynamicArrayList (int tableSize, chainNode **chainListArray)
{

    // create dynamic array of pointers
    chainListArray = new (nothrow) chainNode*[tableSize];

    // allocate each pointer in array
    for (int i=0; i < tableSize; i++)
    {
        chainListArray[i]= CreateNewChainNode(0);
    }

    return;
}


bool SeparateChainInsert (int keyValue, int hashAddress, chainNode **chainListArray)
{
    bool isInserted = false;
    chainNode *newNode;

    newNode = CreateNewChainNode(keyValue);    // create new node

    // if memory allocation did not fail, insert new node into hash table
    if (newNode != NULL)
    {
        //if array cell at hash address is empty
        if (chainListArray[hashAddress]->next == NULL)
        {
            // insert new node to front of list, keeping next pointer still set to NULL
            chainListArray[hashAddress]->next = newNode;

        }
        else //else cell is pointing to a list of nodes already
        {
            // new node's next pointer will point to former front of linked list
            newNode->next = chainListArray[hashAddress]->next;

            // insert new node to front of list
            chainListArray[hashAddress]->next = newNode;

        }

        isInserted = true;
        cout << keyValue << " inserted into chainListArray at index " << hashAddress << endl;
    }

    return isInserted;
}

/*
* Functions to fill array with random numbers for hashing
*/

void FillNumArray (int randomArray[])
{
    int i = 0;                                  // counter for for loop
    int randomNum = 0;                          // randomly generated number

    for (i = 0; i < ARRAY_SIZE; i++)            // do this for entire array
    {
        randomNum = GenerateRandomNum();             // get a random number

        while(!IsUniqueNum(randomNum, randomArray))  // loops until random number is unique
        {
               randomNum = GenerateRandomNum();
        }

        randomArray[i] = randomNum;                  // insert random number into array
    }

    return;
}


int GenerateRandomNum ()
{
    int num = 0;                               // randomly generated number

    // generate random number between start and end ranges
    num = (rand() % END_RANGE) + START_RANGE;

    return num;
}

bool IsUniqueNum (int num, int randomArray[])
{
    bool isUnique = true;         // indicates if number is unique and NOT in array
    int index = 0;                // array index

        //loop until end of array or a zero is found
        //(since array elements were initialized to zero)
        while ((index < ARRAY_SIZE) && (!randomArray[index] == 0))
        {
            // if a value in the array matches the num passed in, num is not unique
            if (randomArray[index] == num)
            {
                isUnique = false;
            }

            index++;            // increment index counter

        }   // end while

    return isUnique;
}



/*
*main
*/

int main (int argc, char* argv[])
{
    int randomNums[ARRAY_SIZE] = {0};     // initialize array elements to 0
    int hashTableSize = 0;                // size of hash table to use
    chainNode **chainListArray;
    bool chainEntry = true;     //testing chain hashing

    //initialize random seed
    srand((unsigned)time(NULL));

    FillNumArray(randomNums);           // fill randomNums array with random numbers

    //test print array
    for(int i = 0; i < ARRAY_SIZE; i++)
    {
        cout << randomNums[i] << endl;
    }

    //test chain hashing insert
    hashTableSize = 19;
    int hashAddress = 0;

    InitDynamicArrayList(hashTableSize, chainListArray);

    //try to hash into hash table
    for (int i = 0; i < ARRAY_SIZE; i++)
    {
        hashAddress = randomNums[i] % hashTableSize;
        chainEntry = SeparateChainInsert(randomNums[i], hashAddress, chainListArray);
    }


    system("pause");
    return 0;
}

Upvotes: 3

Views: 43789

Answers (2)

ssuljic
ssuljic

Reputation: 1081

Your code is good, but it's about how you declared your InitDynamicArrayList. One way is to use ***chainListArray, or the more C++-like syntax to use references like this:

void InitDynamicArrayList (int tableSize, chainNode **&chainListArray)

Upvotes: 0

Ed Swangren
Ed Swangren

Reputation: 124622

arrayOfPointers = new node*[arraySize];

That returns a bunch of unallocated pointers. Your top level array is fine, but its elements are still uninitialized pointers, so when you do this:

->next

You invoke undefined behavior. You're dereferencing an uninitialized pointer.

You allocated the array properly, now you need to allocate each pointer, i.e.,

for(int i = 0; i < arraySize; ++i) {
    arrayOfPointers[i] = new node;
}

As an aside, I realize that you're learning, but you should realize that you're essentially writing C here. In C++ you have a myriad of wonderful data structures that will handle memory allocation (and, more importantly, deallocation) for you.

Upvotes: 9

Related Questions