Array of Linked Lists C++

40,583
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.

Share:
40,583
Ducksauce88
Author by

Ducksauce88

Computer Science Major and I rep Regis University. Still fresh in the field. I also work for Intel Corporation. Trying to secure a permanent job programming at my current job.

Updated on January 30, 2020

Comments

  • Ducksauce88
    Ducksauce88 about 4 years

    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;
    }