电话号码的快速查找

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

 

 

#pragma once

#include <string>
#include <stack>

using namespace std;

#define MAX_WAY				11
#define HAS_CHILDREN_NO     0x01
#define HAS_CHILDREN_YES    0x02
#define HASNO_CHILDREN_NO   0x03
#define HASNO_CHILDREN_YES  0x04


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


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 电话号码本是一个方便人们管理联系方式的工具,如何通过C语言快速查找电话号码本中的联系人信息呢? 首先,我们需要将电话号码本的联系人信息存储在某种数据结构中,比如可以使用哈希表、树或链表等。然后,我们可以通过输入联系人姓名或电话号码快速查找对应的联系人信息。 对于哈希表的实现,我们可以将联系人姓名或电话号码作为关键字进行哈希,并将哈希值作为数组下标存储在数组中。当输入联系人姓名或电话号码时,我们可以通过哈希函数计算出对应的哈希值,并在数组中查找对应的联系人信息。 对于树或链表的实现,我们可以将联系人信息按照某种规则排序,然后建立相应的树或链表结构。当输入联系人姓名或电话号码时,我们可以通过树或链表的遍历算法快速查找对应的联系人信息。 需要注意的是,实现电话号码本的快速查找需要考虑到效率和维护成本之间的平衡。不同的数据结构适用于不同的情况,需要根据具体需求进行选择。另外,还需要注意数据结构的设计和实现的可维护性,方便后续的更新和维护。 ### 回答2: 电话号码本是我们日常生活中非常常见的工具,也是电话沟通的重要辅助工具。为了更方便快捷地查询电话号码,我们可以利用c语言编写一个简单的电话号码快速查找程序。 首先,要实现快速查找功能,我们需要将电话号码本中所有的号码存储到程序中。这可以使用c语言中的数组来实现。我们定义一个二维数组,其中一维存储用户名,另一维存储电话号码。例如,数组名为“phonebook”,则第i个联系人的用户名和电话号码可以分别存储在phonebook[i][0]和phonebook[i][1]中。 接下来,我们需要编写一个函数来实现快速查找功能。这个函数的输入参数为要查找的用户名,输出是其对应的电话号码。使用线性查找的方法,从数组第一个元素开始,逐个遍历每个元素,直到找到和输入参数相同的用户名,然后返回其对应的电话号码即可。 为了进一步提高查找效率,我们可以将电话号码本中的联系人按照字母顺序进行排序,然后再使用二分查找来进行快速查找。这样可以减少查找的时间复杂度,提升程序运行效率。 在实现过程中,为了用户可以方便地进行操作,我们可以加入一些菜单,如添加联系人、删除联系人等功能。 总之,c语言可以轻松实现电话号码本的快速查找功能,提高我们平时的沟通效率。 ### 回答3: 电话号码本是一个简单实用的工具,我们可以通过手机号码、姓名、地址等信息来查询联系人的电话号码及其他联系方式。在现代社会,电话号码本已被电子设备所代替,但依然有人喜欢使用传统的电话号码本。下面介绍如何使用C语言实现电话号码本的快速查找。 首先,我们需要使用结构体来存储联系人信息,如姓名、电话号码、地址等。然后,使用链表来存储这些联系人信息。链表可以按照字母顺序排序,这样可以快速查找联系人。当然,也可以使用其他数据结构如二叉查找树等。 接着,我们需要实现各种功能,比如添加联系人、删除联系人、修改联系人信息、查找联系人等等。在C语言中,可以使用指针来实现链表的添加、删除等操作,代码会非常简洁。 对于查找联系人功能,我们可以实现一个快速查找算法。在链表已经按照字母顺序排序的情况下,可以使用二分查找查找目标联系人。如果链表长度太长,则可以考虑使用哈希表等数据结构来提高查找速度。 最后,我们需要设计一个用户界面,让用户可以方便地使用各种功能,并且对数据进行保存和读取。C语言可以使用控制台窗口来实现用户界面,也可以使用Qt等GUI库来实现更好的用户体验。 综上所述,使用C语言实现电话号码本的快速查找虽然有一定难度,但是只要使用合适的数据结构和算法,就可以实现高效的查询和操作。同时,还需要注意保护用户隐私并及时更新数据,以保证电话号码本的实用性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值