The key-tree algorithm is very common in the billing system. It is used to search for user data in the shared memory, and the search cost is always constant.
The following code is widely used in domestic billing systems. The alloctor and dealloctor functions are used to allocate and release memory in shared memory. For more information, see my article.
Write your own memory allocation program for the c ++ standard library container
In addition, the duplicate key value algorithm uses the Linear Linked List algorithm, which is relatively simple, so the source code is not listed.
H_trie.h
# Ifndef h_trie_h _
# Define h_trie_h _
# Include <stdio. h>
# Include <stdlib. h>
# Include <string. h>
# Include "error. H"
# Include "list. H"
# Define trie_fanout 10
/*---Key Tree node Structure ---*/
Typedef struct trie_s
{
Int subchanged [trie_fanout];/* records the change of the subnode */
Int listchanged;/* record the changes in the linked list */
List_t * List;
Struct trie_s * subtrie [trie_fanout];
} Trie_t;
Void inithtrie (trie_t ** trie );
Int inserthtrie (trie_t ** trie, const char STR [], const int level,
Void * data, size_t N, int changed );
Void * searchhtrie (trie_t * trie, const char STR [], const int level, void * data,
INT (* CMP) (const void * data1, const void * data2 ));
Int touchhtrie (trie_t ** trie, const char STR [], const int level, list_t *** list );
List_t * getlistofhtrie (trie_t * trie, const char STR [], const int level );
Void printhtrie (trie_t * trie, const int level, const int key,
Void (* print) (const void * Data ));
/*
Void operatetrie (trie_t * trie, void (* op_list) (void * Data ));
*/
Void refreshhtrie (trie_t * trie, void (* op_data) (void * Data ));
Void freehtrie (trie_t * trie );
Int needrefresh (trie_t * trie );
/*
* Maximum possible matching tree search
*/
List_t * matchhtrie (trie_t * trie, const char STR [], const int level );
/*
* Function: trie tree traversal operation function
*
* Note that node operations can be interrupted.
*
* 0 is returned. execution is not completed. 1 is finished.
*/
Int dealhtrie (trie_t * trie, INT (* op_data) (void * Data ));
# Endif
H_trie.c
# Include "stdafx. H"
# Include <stdio. h>
# Include <ctype. h>
# Include "h_trie.h"
# Include "alloc. H"
Static char keyarray [256];
/*-------------------------------
* Usage: initializes an array of key values.
* Comment: maps Char to 0-9 values.
*-------------------------------*/
Void inithtrie (trie_t ** trie)
{
Int C;
For (C = 0; C <256; C ++)
{
If (isdigit (c ))
Keyarray [c] = C-'0 ';
Else
Keyarray [c] = C % 10;
}
* Trie = NULL;
}
Static trie_t * newnode ()
{
Int I;
Trie_t * node = (trie_t *) Allocate (sizeof (trie_t ));
If (node)
{
Node-> List = NULL;
For (I = 0; I <trie_fanout; I ++)
{
Node-> subchanged [I] = 0;
Node-> listchanged = 0;
Node-> subtrie [I] = NULL;
}
}
If (node = NULL)
Pr_error ("errorcode: % d, MSG: newnode: allocate () return null/N ");
Return node;
}
/*--------------------------------
* Usage: inserts a new data into the key tree.
* Arguments: * trie -- Key tree header pointer
* Str -- Key-value string
* Level -- key value Length
* Data -- data to be inserted
* N -- size of the data to be inserted
* Changed-record whether the content of the subnode of the current node has changed
* 1 -- changed 0 -- not changed
* Return:-1 -- error 0 -- normal
* Comment: The leaf node of the key tree is a linked list. When reading and writing data, locate the leaf node based on the key value before
* Insert data into the linked list referred to by the leaf node.
*---------------------------------*/
Int inserthtrie (trie_t ** trie, const char STR [], const int level,
Void * data, size_t N, int changed)
{
Int I;
Int key;
Trie_t * curnode;
If (* trie = NULL)
{
* Trie = newnode ();
If (* trie = NULL ){
Return-1;
}
}
Curnode = * trie;
For (I = 0; I <level; I ++)
{
Key = (INT) keyarray [(INT) STR [I];
If (curnode-> subtrie [Key] = NULL)
{
If (curnode-> subtrie [Key] = newnode () = NULL)
Return-1;
}
Curnode-> subchanged [Key] = changed;
Curnode = curnode-> subtrie [Key];
}
Curnode-> listchanged = changed;
Return (insertlist (& (curnode-> list), data, n ));
}
/*--------------------------------
* Usage: Search for data in the key tree
* Arguments: trie -- Key tree header pointer
* Str -- Key-value string
* Level -- key value Length
* Data -- the data to be searched
* CMP -- Comparison function pointer
* Return: locate -- the pointer pointing to the data is not found. -- null
* Comment: the query rule is specified by the CMP function.
*---------------------------------*/
Void * searchhtrie (trie_t * trie, const char STR [], const int level, void * data,
INT (* CMP) (const void * data1, const void * data2 ))
{
Int I;
Int key;
Trie_t * curnode;
If (trie = NULL)
Return NULL;
Curnode = trie;
For (I = 0; I <level; I ++)
{
Key = (INT) keyarray [(INT) STR [I];
If (curnode-> subtrie [Key] = NULL)
Return NULL;
Curnode = curnode-> subtrie [Key];
}
Return (searchlist (curnode-> list, Data, CMP ));
}
/*--------------------------------
* Usage: Search for the chain header to which the key value points in the key tree. Set the changed field of the passed node to 1.
* Indicates that the subnode of the node needs to change. If the node does not exist, the node is generated.
* Arguments: trie -- Key tree header pointer
* Str -- Key-value string
* Level -- key value Length
* List -- save the pointer pointing to the chain head list pointer. Because you want to save the pointer,
* Use a layer-3 pointer
* Return: locate -- the pointer pointing to the head of the linked list is not found. -- null
* Comment:
*---------------------------------*/
Int touchhtrie (trie_t ** trie, const char STR [], const int level, list_t *** List)
{
Int I;
Int key;
Trie_t * curnode;
If (* trie = NULL)
{
* Trie = newnode ();
If (* trie = NULL ){
Pr_error ("errorcode: % d, MSG: touchhtrie: newnode () return null/N ");
Return-1;
}
}
Curnode = * trie;
For (I = 0; I <level; I ++)
{
Key = (INT) keyarray [(INT) STR [I];
If (curnode-> subtrie [Key] = NULL)
{
If (curnode-> subtrie [Key] = newnode () = NULL ){
Pr_error ("errorcode: % d, MSG: newnode () Error/N ");
Return-1;
}
}
Curnode-> subchanged [Key] = 1;
Curnode = curnode-> subtrie [Key];
}
Curnode-> listchanged = 1;
* List = & (curnode-> list );
Return 0;
}
/*-------------------------------------------
*
*-------------------------------------------*/
List_t * getlistofhtrie (trie_t * trie, const char STR [], const int level)
{
Int I;
Int key;
Trie_t * curnode;
If (trie = NULL)
Return NULL;
Curnode = trie;
For (I = 0; I <level; I ++)
{
Key = (INT) keyarray [(INT) STR [I];
If (curnode-> subtrie [Key] = NULL)
Return NULL;
Curnode = curnode-> subtrie [Key];
}
Return curnode-> list;
}
List_t * matchhtrie (trie_t * trie, const char STR [], const int level)
{
Int I;
Int key;
Trie_t * curnode;
If (trie = NULL)
Return NULL;
Curnode = trie;
For (I = 0; I <level; I ++)
{
Key = (INT) keyarray [(INT) STR [I];
If (curnode-> subtrie [Key] = NULL)
Return curnode-> list;
Curnode = curnode-> subtrie [Key];
}
Return curnode-> list;
}
/*-------------------------------
* Usage: Release the key tree
* Arguments: trie -- the head of Trie
*-------------------------------*/
Void freehtrie (trie_t * trie)
{
Int I;
If (trie)
{
For (I = 0; I <trie_fanout; I ++)
Freehtrie (Trie-> subtrie [I]);
Freelist (Trie-> list );
Free (trie );
}
}
/*----------------------------------
* Usage: print the data of the Trie
*----------------------------------*/
Void printhtrie (trie_t * trie, const int level, const int key, void (* print) (const void * Data ))
{
Int I;
If (trie)
{
Fprintf (stderr, "Enter subtrie -- level: % d, key: % d/N", level, key );
For (I = 0; I <trie_fanout; I ++)
{
Printhtrie (Trie-> subtrie [I], level + 1, I, print );
}
Printlist (Trie-> list, print );
}
}
/*
Void operatehtrie (trie_t * trie, void (* op_list) (void * Data ))
{
}
*/
/*------------------------------------------
* Usage: refresh trie and perform the operation specified by op_list on the linked list of subnodes of changed to 1.
* Parameters: trie -- trie head pointer
* Op_list -- List Operation
*------------------------------------------*/
Void refreshhtrie (trie_t * trie, void (* op_data) (void * Data ))
{
Int I;
If (trie)
{
For (I = 0; I <trie_fanout; I ++)
{
If (Trie-> subchanged [I])/* The subnode has changed */
{
Refreshhtrie (Trie-> subtrie [I], op_data );
Trie-> subchanged [I] = 0;
}
}
If (Trie-> listchanged)
{
Operatelist (Trie-> list, op_data );
Trie-> listchanged = 0;
}
}
}
Int needrefresh (trie_t * trie)
{
Int I;
If (trie)
{
For (I = 0; I <trie_fanout; I ++)
{
If (Trie-> subchanged [I])/* The subnode has changed */
{
Return 1;
}
}
If (Trie-> listchanged)
{
Return 1;
}
}
Return 0;
}
/*
* Function: trie tree traversal operation function
*
* Note that node operations can be interrupted.
*
* 0 is returned. execution is not completed. 1 is finished.
*/
Int dealhtrie (trie_t * trie, INT (* op_data) (void * Data ))
{
Int I;
If (trie)
{
For (I = 0; I <trie_fanout; I ++)
{
If (Trie-> subchanged [I])/* The subnode has changed */
{
/* The Byte point operation is interrupted. 0 is returned */
If (dealhtrie (Trie-> subtrie [I], op_data) = 0)
Return 0;
Trie-> subchanged [I] = 0;
}
}
If (Trie-> listchanged)
{
If (deallist (Trie-> list, op_data) = 0)
Return 0;
Trie-> listchanged = 0;
}
}
Return 1;
}
The main program of the test is compiled in vs2005
# Include "stdafx. H"
# Include <stdio. h>
# Include <stdlib. h>
# Include "alloc. H"
# Include "list. H"
# Include "h_trie.h"
Static trie_t * ptrie;
Struct testdata
{
Int key;
Char data [20];
};
Int _ tmain (INT argc, _ tchar * argv [])
{
Struct testdata * pdata;
Int I;
Char key [10];
Initshm (sizeof (trie_t) * 100 + sizeof (list_t) * 20 );
Printfreelistandcookie ();
Inithtrie (& ptrie );
For (I = 0; I <10; I ++)
{
Printf ("Main: I = % d/N", I );
Pdata = (struct testdata *) malloc (sizeof (struct testdata ));
If (pdata = NULL)
{
Pr_error ("allocate fail/N ");
}
Pdata-> key = I;
Sprintf (pdata-> data, "% d", I * 9999 );
Sprintf (key, "% d", pdata-> key );
If (-1 = inserthtrie (& ptrie, key, sizeof (INT), pdata,
Sizeof (struct testdata), 0 ))
{
Pr_error ("errorcode: % d, MSG: insert tree error/N ");
}
Printfreelistandcookie ();
}
Free (getshm ());
Return 0;
};