Saturday, June 11, 2016

Source code for a Trie Dictionary

This is a piece of code for inserting a string into a Trie dictionary. This is a bit complicated but it works.


#ifndef TYPETRIE_H
#define TYPETRIE_H

#include <stdio.h>
#include <stdlib.h>

#define TRIE_ROOT     01
#define TRIE_BRANCH   02
#define TRIE_LEAF     03

typedef struct tagNode
  {
  long          Type;
  unsigned long Length;
  char*         Data;
  tagNode*      Child;
  tagNode*      Next;
  } typeNode;

long trieCreate(typeNode* working)
  {
  working->Type   = TRIE_ROOT;
  working->Length = 0;
  working->Data   = 0;
  working->Child  = 0;
  working->Next   = 0;

  return 1;
  }

static typeNode* CreateNode(unsigned long type)
  {
  typeNode*   working;

  working = (typeNode*)malloc(sizeof(typeNode));
  if (working == 0)
    return 0;

  working->Type   = type;
  working->Length = 0;
  working->Data   = 0;
  working->Child  = 0;
  working->Next   = 0;

  return working;
  }

static typeNode* CreateBranch(typeNode* parent,char* buffer,unsigned long buffersize)
  {
  typeNode*     working;
  char*         data;
  unsigned long I;

  working = CreateNode(TRIE_BRANCH);
  if (working == 0)
    return 0;

  data = (char*)malloc(buffersize);
  if (data == 0)
    return 0;

  for (I = 0;I < buffersize;I++)
    data[I] = buffer[I];

  working->Length = buffersize;
  working->Data   = data;

  if (parent)
    {
    working->Next   = parent->Child;
    parent->Child   = working;
    }

  return working;
  }

static typeNode* SplitBranch(typeNode* parent,unsigned long index)
  {
  typeNode*     working;
  char*         data;
  unsigned long I;

  if ((index < 1) || (index >= parent->Length))
    return 0;

  working = CreateBranch(0,parent->Data + index,parent->Length - index);
  if (working == 0)
    return 0;

  working->Child = parent->Child;
  parent->Child = working;

  data = (char*)malloc(index);
  if (data == 0)
    return 0;

  for (I = 0;I < index;I++)
    data[I] = parent->Data[I];

  free(parent->Data);

  parent->Length = index;
  parent->Data   = data;

  return working;
  }

static typeNode* FindBranch(typeNode* parent,char value)
  {
  typeNode*      working;

  working = parent->Child;

  while (working)
    {
    if (working->Type == TRIE_BRANCH)
      {
      if (working->Data[0] == value)
        return working;
      }

    working = working->Next;
    }

  return 0;
  }

static typeNode* CreateLeaf(typeNode* parent)
  {
  typeNode*      working;

  working = CreateNode(TRIE_LEAF);
  if (working == 0)
    return 0;

  working->Next = parent->Child;
  parent->Child = working;

  return working;
  }

static long FindLeaf(typeNode* parent)
  {
  typeNode*      working;

  working = parent->Child;

  while (working)
    {
    if (working->Type == TRIE_LEAF)
      return 1;

    working = working->Next;
    }

  return 0;
  }

long trieFind(typeNode* root,char* buffer,unsigned long buffersize)
  {
  typeNode*     working;
  typeNode*     result;
  unsigned long I,J;

  working = root;
  if (working == 0)
    return 0;

  I = 0;
  while (I < buffersize)
    {
    result = FindBranch(working,buffer[I]);

    if (result == 0)
      return 0;
    else
      working = result;

    J = 0;
    while (J < working->Length)
      {
      if (buffer[I] != working->Data[J])
        return 0;

      if (I >= buffersize)
        return 0;

      I++;
      J++;
      }
    }

  return FindLeaf(working);
  }

long trieInsert(typeNode* root,char* buffer,unsigned long buffersize)
  {
  typeNode*     working;
  typeNode*     result;
  unsigned long I,J;

  working = root;
  if (working == 0)
    return 0;

  I = 0;
  while (I < buffersize)
    {
    result = FindBranch(working,buffer[I]);

    if (result == 0)
      {
      working = CreateBranch(working,buffer + I,buffersize - I);
      break;
      }
    else
      working = result;

    J = 0;
    while (J < working->Length)
      {
      if (buffer[I] != working->Data[J])
        {
        SplitBranch(working,J);
        working = CreateBranch(working,buffer + I,buffersize - I);
        I = buffersize;

        break;
        }

      if (I >= buffersize)
        {
        SplitBranch(working,J);

        break;
        }

      I++;
      J++;
      }
    }

  if (working == 0)
    return 0;

  if (FindLeaf(working) == 0)
    CreateLeaf(working);

  return 1;
  }

long trieInsertCString(typeNode* root,const char* buffer)
  {
  unsigned long I;

  I = 0;
  while ((buffer[I] != 0) && (I < STRING_MAX))
    I++;

  return trieInsert(root,(char*)buffer,I);
  }

int trieDraw(typeNode* root,int indent)
  {
  typeNode*   working;

  if (root == 0)
    return 0;

  if (root->Type == TRIE_ROOT)
    printf("\nRoot\n");
  else
  if (root->Type == TRIE_BRANCH)
    {
    printf("%*s\"",indent," ");
    fwrite(root->Data,1,root->Length,stdout);
    printf("\"\n");
    }

  working = root->Child;

  while (working)
    {
    trieDraw(working,indent + 2);

    working = working->Next;
    }

  return 1;
  }

long trieDestroy(typeNode* parent)
  {
  typeNode* working;
  typeNode* temp;

  if (parent->Type == TRIE_BRANCH)
    free(parent->Data;
 
  working = (parent->Child);

  while (working)
    {
    temp = working->Next;

    trieDestroy(working);
    free(working);

    working = temp;
    }

  return 1;
  }

#endif // TYPETRIE_H

No comments:

Post a Comment