电话号码的快速查找

来源:互联网 发布:linux查看检测网络命令 编辑:程序博客网 时间:2024/04/16 15:28

在一个嵌入式项目中,要存储100万条电话号码,同时电话号码的长度最长为11位,为了提高查找的速度,笔者采用11叉树的方式进行存储电话号码,并且支持电话号码的包含关系,所谓包含关系,即要支持1234, 12345这种包含关系。

 

 

#pragma once#include <string>#include <stack>using namespace std;#define MAX_WAY11#define HAS_CHILDREN_NO     0x01#define HAS_CHILDREN_YES    0x02#define HASNO_CHILDREN_NO   0x03#define HASNO_CHILDREN_YES  0x04class Threewaytree{public:Threewaytree(void);~Threewaytree(void);private:Threewaytree* m_ptree[MAX_WAY];unsigned char m_symbol;static int m_nodecount;public:void output(int indent = -1);bool insertphonenumber(string phonenumber);bool deletephonenumber(string phonenumber);void generatephonelist(string& prefix);void getphonecount(int& count);bool findphonenumber(string phonenumber);private:void destroy();int  wetherornotdelete();bool islegalphonenumber(string phonenumber);};#include "Threewaytree.h"#include "stdio.h"int Threewaytree::m_nodecount = 0;Threewaytree::Threewaytree(void){//printf("new %08x\n", this);m_nodecount++;m_symbol = 0x00;for(int i = 0; i < MAX_WAY; i++){m_ptree[i] = NULL;}}Threewaytree::~Threewaytree(void){printf("delete %08x\n", this);m_nodecount--;destroy();}void Threewaytree::getphonecount(int& count){for(int i = 0; i < MAX_WAY; i++){if (m_ptree[i] != NULL){if (m_ptree[i]->m_symbol == 1){count++;}m_ptree[i]->getphonecount(count);}}}void Threewaytree::generatephonelist(string& prefix){for(int i = 0; i < MAX_WAY; i++){string temp = prefix;if (m_ptree[i] != NULL){temp += i + 48;if (m_ptree[i]->m_symbol == 1){printf("%s\n", temp.c_str());}m_ptree[i]->generatephonelist(temp);}}}void Threewaytree::output(int indent){indent++;for(int i = 0; i < MAX_WAY; i++){if (m_ptree[i] != NULL){for(int j = 0; j < indent; j++){printf("|--");}printf("%d [0x%08x] [%d] \n", i, m_ptree[i], m_ptree[i]->m_symbol);m_ptree[i]->output(indent);}}}bool Threewaytree::insertphonenumber(string phonenumber){bool result = false;if (!islegalphonenumber(phonenumber)) return false;const char *pchar = phonenumber.c_str();int index = 0;int length = phonenumber.length();Threewaytree *parenttreenode = this;int order = 0;while(index < length){order = *pchar - 48;if (parenttreenode->m_ptree[order] == NULL){Threewaytree *treenode = new Threewaytree;parenttreenode->m_ptree[order] = treenode;parenttreenode = treenode;}else{parenttreenode = parenttreenode->m_ptree[order];}index++;pchar++;}if (parenttreenode->m_symbol == 1) {return result;}else if(parenttreenode->m_symbol == 0){result = true;parenttreenode->m_symbol = 1;}return result;}bool Threewaytree::islegalphonenumber(string phonenumber){bool result = true;int length = phonenumber.length();if (length > MAX_WAY) {result = false;return result;}const char *pchar = phonenumber.c_str();int index = 0;while(index < length){if ((*pchar) < '0' || (*pchar > '9')){result = false;break;}index++;pchar++;}return result;}int Threewaytree::wetherornotdelete(){int result = 0x00;bool haschildren = false;for(int i = 0; i < MAX_WAY; i++){if (m_ptree[i] != NULL){haschildren = true;break;}}if(haschildren == true && m_symbol == 1){result = HAS_CHILDREN_YES;}else if(haschildren == false && m_symbol == 1){result = HASNO_CHILDREN_YES;}else if(haschildren == true && m_symbol == 0){result = HAS_CHILDREN_NO;}else if(haschildren == false && m_symbol == 0 ){result = HASNO_CHILDREN_NO;}return result;}bool Threewaytree::findphonenumber(string phonenumber){bool result = false;if (!islegalphonenumber(phonenumber)) return result;const char *pchar = phonenumber.c_str();int length = phonenumber.length();int index = 0;Threewaytree *node = this;while(index < length){int order = *pchar - 48;//不存在号码退出, 号码还没有遍历完,但指针已经到头了。if (node->m_ptree[order] == NULL) return result;//为下次循环准备node = node->m_ptree[order];pchar++;index++;}if (node->m_symbol == 1){result = true;}return result;}bool Threewaytree::deletephonenumber(string phonenumber){typedef struct{int index;Threewaytree* ptree;}ELEM;typedef stack<ELEM> STACK;STACK mystack;bool result = false;if (!islegalphonenumber(phonenumber)) return result;const char *pchar = phonenumber.c_str();int length = phonenumber.length();int index = 0;Threewaytree *node = this;//都元素入栈ELEM elem;elem.index = 0xFFFFFFFF;elem.ptree = node;mystack.push(elem);while(index < length){int order = *pchar - 48;//不存在号码退出, 号码还没有遍历完,但指针已经到头了。if (node->m_ptree[order] == NULL) return result;//普通元素开始入栈ELEM elem;elem.index = order;elem.ptree = node->m_ptree[order];mystack.push(elem);//为下次循环准备node = node->m_ptree[order];pchar++;index++;}printf("-----------------------------  stack size = %d ---------------------------------\n", mystack.size());for(int i= 0; i < length; i++){ELEM elem1 = mystack.top();mystack.pop();int result = elem1.ptree->wetherornotdelete();printf("pop order=%d elem=%08x symbol=%d  result=%d\n", elem1.index, elem1.ptree, elem1.ptree->m_symbol, result);if (result == HAS_CHILDREN_NO){break;}else if(result == HAS_CHILDREN_YES){if (i == 0){elem1.ptree->m_symbol = 0;printf("set symbol = 0\n");break;}}else if(result == HASNO_CHILDREN_NO){delete elem1.ptree;elem1.ptree = NULL;ELEM elem2 = mystack.top();elem2.ptree->m_ptree[elem1.index] = NULL;}else if(result == HASNO_CHILDREN_YES){if (i== 0){delete elem1.ptree;elem1.ptree = NULL;ELEM elem2 = mystack.top();elem2.ptree->m_ptree[elem1.index] = NULL;}else{break;}}}result = true;printf("------------------------------------------------------------------------------\n");return result;}void Threewaytree::destroy(){for(int i = 0; i < MAX_WAY; i++){if (m_ptree[i] != NULL){m_ptree[i]->destroy();delete m_ptree[i];m_ptree[i] = NULL;}}}


主函数测试:

// Tree.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include "Threewaytree.h"#include "math.h"int _tmain(int argc, _TCHAR* argv[]){Threewaytree tree;tree.insertphonenumber("123");tree.insertphonenumber("123");tree.insertphonenumber("12");tree.insertphonenumber("1234");tree.insertphonenumber("123567");tree.insertphonenumber("125");tree.insertphonenumber("18");tree.insertphonenumber("2");tree.output();    string phonelist = "";tree.generatephonelist(phonelist);  bool result = tree.deletephonenumber("2");if (result){printf("delete true\n");}else{printf("delete false\n");}tree.generatephonelist(phonelist); tree.output();/*tree.output();printf("-------------- phone number count ----------------\n");int count = 0;tree.getphonecount(count);printf("count=%d\n", count);printf("-------------- phone number list ----------------\n");string phonelist = "";tree.generatephonelist(phonelist);  printf("-------------- find phone number ----------------\n");string phonenumber = "18";if (tree.findphonenumber(phonenumber)){printf("find\n");}else{printf("not find\n");}*/getchar();return 0;}