[ create a new paste ] login | about

Link: http://codepad.org/uhesUQZJ    [ raw code | output | fork ]

olnrao - C, pasted on Dec 8:
// Linked List with Random Pointer - Duplicate and Reverse
// Assumption: No two random pointers are pointing to the same node (except if NULL)
//

#include <stdio.h>

//#define DEBUG_PRINT

#define SIZEOFARRAY(arr)  (sizeof((arr))/sizeof((arr)[0]))

typedef struct Node
{
  struct Node *pNext;
  struct Node *pRandom;
  int data;
} node_t;

struct Node*   CreateList(int nData, int  *pData, int *pRandom);
void           PrintList(struct Node *pHead, char *pContext);
struct Node*   FreeList(struct Node *pList);
struct Node*   DuplicateList(struct Node *pList);
struct Node*   ReverseList(struct Node *pList);

int main(int argc, char *args[])
{
  int dataSize, randomSize;
  int *pData, *pRandom;
  struct Node *pList = NULL, *pNewList = NULL; 

  int data1[] = {10, 20, 30, 40, 50};
  int random1[] = {40, -1, -1, -1, 20};

  printf("\n");

  dataSize = SIZEOFARRAY(data1); pData = (int *) data1;
  randomSize = SIZEOFARRAY(random1); pRandom = (int *)random1;
  if (dataSize != randomSize) { printf("ERROR: Invalid Input\n"); return -1; }
  pList = CreateList(dataSize, pData, pRandom); PrintList(pList, "Input"); 
  pNewList = DuplicateList(pList); 
  PrintList(pNewList, "Copy"); 
  pNewList = ReverseList(pNewList);
  PrintList(pNewList, "Reverse"); 
  pNewList = FreeList(pNewList); 
  pList = FreeList(pList);

  return 0;
}

struct Node*  ReverseList(struct Node *pList)
{
  struct Node *pMover, *pMoverNext, *pNewHead;
  struct Node *pTrav, *pTravRandom, *pRandHead; 
  struct Node *pReverseTail = NULL;
  int isHead = 0;

  // Reverse Next Pointers
  for(pMover = pList, pNewHead = NULL; pMover; pMover = pMoverNext)
  {
    pMoverNext = pMover->pNext;
    pMover->pNext = pNewHead;
    pNewHead = pMover;
  }

  pReverseTail = (struct Node*) malloc(sizeof(struct Node));
  pReverseTail->pNext = pReverseTail->pRandom = pReverseTail;
  pReverseTail->data = 0;

  for (pMover = pNewHead; pMover; pMover = pMoverNext)
  {
    pMoverNext = pMover->pNext;

    if (NULL == pMover->pRandom) continue;

    // Check if this is head in random-pointer linked list
    isHead = 1;
    for (pTrav = pNewHead; isHead && pTrav; pTrav = pTrav->pNext)
    {
      if (pTrav->pRandom == pMover) { isHead = 0; break; }
    }

    if (isHead)
    {
      // If already reversed (i.e. reversed list head), then do not do it again
      for (pTrav = pMover; isHead && pTrav; pTrav = pTrav->pRandom)
      {
        if (pTrav == pReverseTail) { isHead = 0; break; }
      }
    }

#ifdef DEBUG_PRINT
    printf("DEBUG: IsHead(%d) = %d\n", pMover->data, isHead);
#endif

    if (isHead)
    {
      for(pTrav = pMover, pRandHead = pReverseTail; pTrav; pTrav = pTravRandom)
      {
        pTravRandom = pTrav->pRandom;
        pTrav->pRandom = pRandHead;
        pRandHead = pTrav;
      }
    }
  }

  // Reset all 'Reverse Tail Head' pointers to NULL
  //
  for (pMover = pNewHead; pMover; pMover = pMover->pNext)
  {
    if (pMover->pRandom == pReverseTail) pMover->pRandom = NULL;
  }

  if (NULL != pReverseTail) free(pReverseTail);

  return pNewHead;
}

struct Node*  DuplicateList(struct Node *pList)
{
  struct Node  *pNode, *pMover, *pHead, *pMoverNext;
  
  pHead = NULL; pNode = NULL; 
  pMover = NULL; pMoverNext = NULL;
  
  // Create duplicate nodes and 
  // insert just after the original node in the same list
  for (pMover = pList; pMover; pMover = pMoverNext)
  {
    pMoverNext = pMover->pNext;

    pNode = (struct Node *) malloc(sizeof(struct Node));
    
    if (NULL == pNode) goto cleanup;
    if (NULL == pHead) pHead = pNode;
    
    pNode->data = pMover->data;
    pNode->pRandom = NULL;
    pNode->pNext = pMover->pNext;
    pMover->pNext = pNode;
  }

  // Set Random Pointers for new nodes
  for (pMover = pList; pMover; pMover = pMover->pNext->pNext)
  {
    pMover->pNext->pRandom = pMover->pRandom ? pMover->pRandom->pNext : NULL;
  }

  // Split the combined list
  for (pMover = pList; pMover; pMover = pMover->pNext)
  {
    pMoverNext = pMover->pNext;
    pNode = pMoverNext->pNext;

    pMover->pNext = pNode;
    pMoverNext->pNext = pNode ? pNode->pNext : NULL;
  }

  return pHead;

cleanup:
  printf("ERROR: Original List is modified and not restorable!\n");
  return NULL;
}

struct Node*  CreateList(int nData, int  *pData, int *pRandom)
{
  struct Node *pHead;
  struct Node *pNode, *pTemp;
  int i;

  if (NULL == pData || nData <= 0) return NULL;
 
  pTemp = NULL; pNode= NULL; pHead = NULL;

  for (i = 0; i < nData; i++)
  {
    pNode = (struct Node *) malloc(sizeof(struct Node));
    
    if (NULL == pNode) goto cleanup;
    if (NULL == pHead) pHead = pNode;
    
    pNode->data = pData[i];
    pNode->pNext = NULL;
    pNode->pRandom = NULL;

    if (NULL != pTemp) { pTemp->pNext = pNode; }
    pTemp = pNode;
  }

  for (i = 0, pNode = pHead; i < nData; i++, pNode = pNode->pNext)
  {
    for (pTemp = pHead; pTemp; pTemp = pTemp->pNext)
    {
      if (pTemp->data == pRandom[i]) break;
    }

    pNode->pRandom = pTemp; 
  }

  return pHead;

cleanup:
  FreeList(pHead);
  return NULL;
}

void PrintList(struct Node *pList, char *pContext)
{
  struct Node *pMover = pList;

  printf("List (%s) :  ", pContext);
  if (NULL == pList) printf(":: EMPTY ::");

  while(pMover)
  {
#ifdef DEBUG_PRINT
    printf("0x%08X = %d (0x%08X = %d), ", pMover, pMover->data, 
      pMover->pRandom, pMover->pRandom ? pMover->pRandom->data : -1);
#else
    printf("%d (%d), ", pMover->data, pMover->pRandom ? pMover->pRandom->data : -1);
#endif

    pMover = pMover->pNext;
  }
  printf("\n");
}

struct Node* FreeList(struct Node *pList)
{
  struct Node *pCurrent, *pNext;

  pCurrent = pList;

  while (pCurrent)
  {
    pNext = pCurrent->pNext;
    pCurrent->pNext = NULL;
    free(pCurrent);
    pCurrent = pNext;
  }

  return NULL;
}


Output:
1
2
3
4

List (Input) :  10 (40), 20 (-1), 30 (-1), 40 (-1), 50 (20), 
List (Copy) :  10 (40), 20 (-1), 30 (-1), 40 (-1), 50 (20), 
List (Reverse) :  50 (-1), 40 (10), 30 (-1), 20 (50), 10 (-1), 


Create a new paste based on this one


Comments: