简单字母索引表--C语言学习笔记

假设有一个有序的字符串链表,链表中的每个节点为一个单词,我们可以使用它来将单词插入到链表,同时不会导致重复,但这样带来的问题是搜索链表的时间会随着链表规模的的扩大而急剧增长。

那么如何缩短这个时间呢?不妨先看看下图:

 

image

 

如上图所看到的数据结构,它的思路是将整个链表分解成26×27个链表,第一个链表存放26个字母,作为一级链表,该链表每个节点还存放一个指针,指向二级链表,二级链表同样存放26个字母,每个节点包含了一个指向单词链表的指针。

单词的第一个字符在一级链表当中找到匹配项,找到匹配进入二级链表,将单词的第二个字符在二级链表找到匹配项,进入单词链表找到整个单词的匹配项。

 

首先先构造一级、二级、单词节点:

#include "stdio.h"
#include "string.h"
#include "ctype.h"
#include "malloc.h"

#define TRUE  1
#define FALSE 0

/*存放单词*/
typedef struct WORD{
	char		*word;
	struct WORD *next;
}Word;

/*二级节点*/
typedef struct SECLIST{
	char letter;
	struct SECLIST *next;
	Word *word_list;
}SecList;

/*一级节点*/
typedef struct FIRSTLIST{
	char		letter;
	struct FIRSTLIST *next;
	SecList *sec_list;
}FirList;

声明:

FirList *fir_cur_list;
SecList **sec_listp;
SecList *sec_cur_list;
Word **wordp;
Word *current_word;

接着是插入函数,该函数需传入指向整个链表根节点的指针和准备插入到链表中的单词.

/*新单词插入*/
int
concordance_insert(FirList **fir_listp,char *the_word)
{
	int  first_char;
	int sec_char;
	int  comparison;
	Word *new_word;

	/*获取第一个字符并确保该字符有效*/
	first_char = *the_word;
	if (!islower(first_char))
	{
		return FALSE;
	}

	/*获取第二个字符并确保该字符有效*/
	sec_char = *(the_word + 1);
	if (!islower(sec_char))
	{
		return FALSE;
	}

	/*根据第一个字符在一级链表中找到匹配项,如果不存在,则创建一个新的节点并插入到一级链表当中*/
	while ((fir_cur_list = *fir_listp)!= NULL && fir_cur_list ->letter next;
	}

	/*如果在一级链表当中,当前节点为null(即到链表的结尾)或者找到一个节点中的字符比第一个字符大的,*/
	/*创建一个新的一级节点,该节点包含一个新的二级链表*/
	if (fir_cur_list == NULL || fir_cur_list->letter > first_char)
	{
		FirList *new_list;

		new_list = (FirList *)malloc(sizeof(FirList));
		if (new_list == NULL)
		{
			return FALSE;
		}

		new_list->letter = first_char;
		new_list->sec_list = NULL;
		new_list->next = fir_cur_list;
		*fir_listp = new_list;
		/*需要将当前节点的指针指向新创建的节点,因为不管是新创建还是已存在的节点,*/
		/*我们都需要知道指向这个节点的指针,方便我们作二级查找*/
		fir_cur_list = new_list;
	}

	/*当前一级节点包含二级链表的根节点,根据第二个字符在二级链表找到匹配项*/
	sec_listp = &fir_cur_list->sec_list;
	while ((sec_cur_list = *sec_listp) != NULL && sec_cur_list->letter < sec_char)
	{
		sec_listp = &sec_cur_list->next;
	}

	/*如果在二级链表当中,当前节点为null(即到链表的结尾)或者找到一个节点中字符比第二个字符大的,*/
	/*创建一个新的二级节点,该节点包含一个新的单词链表*/
	if (sec_cur_list == NULL || sec_cur_list->letter > sec_char)
	{
		SecList *new_sec_list;
		new_sec_list = (SecList *)malloc(sizeof(SecList));
		if (new_sec_list == NULL)
		{
			return FALSE;
		}

		new_sec_list->letter = sec_char;
		new_sec_list->word_list = NULL;
		new_sec_list->next = sec_cur_list;
		*sec_listp = new_sec_list;
		sec_cur_list = new_sec_list;
	}

	/*当前二级节点包含单词链表的根节点,根据第the_word在单词链表找到匹配项*/
	wordp = &sec_cur_list->word_list;
	while ((current_word = *wordp)!= NULL)
	{
		comparison = strcmp(current_word->word,the_word);
		if (comparison >= 0)
		{
			break;
		}
		wordp = ¤t_word->next;
	}

	/*如果当前单词节点不为0且比较结果等于,该单词已经存在于链表当中*/
	if (current_word != NULL && comparison == 0)
	{
		return FALSE;
	}

	new_word = (Word *)malloc(sizeof(Word));
	if (new_word == NULL)
	{
		return FALSE;
	}

	/*创建一个新的单词节点存放单词*/
	new_word->word = (char *)malloc(strlen(the_word) + 1);
	if (new_word->word == NULL)
	{
		return FALSE;
	}

	strcpy(new_word->word,the_word);

	/*将新节点接入到链表当中*/
	new_word->next = current_word;
	*wordp = new_word;

	return TRUE;
}

打印整个索引表:

/*打印整个索引表*/
void 
printf_table(FirList **fir_listp)
{
	while((fir_cur_list = *fir_listp) != NULL)
	{
		printf("%c",fir_cur_list->letter);
		putchar('\n');
		sec_listp = &fir_cur_list->sec_list;
		while((sec_cur_list=*sec_listp) != NULL)
		{
			printf("%c",sec_cur_list->letter);
			putchar('\n');
			wordp = &sec_cur_list->word_list;
			while((current_word = *wordp) != NULL)
			{
				printf("%s",current_word->word);
				putchar('\n');
				wordp = ¤t_word->next;
			}
			sec_listp=&sec_cur_list->next;
		}
		fir_listp = &fir_cur_list->next;
	}
}

int
main()
{
	char message[] = "ziqi";
	FirList **listp;
	FirList *root;
	FirList list;
	list.letter=' ';
	list.next = NULL;
	list.sec_list = NULL;
	root = &list;
	listp = &root;
	concordance_insert(listp,message);
	printf_table(listp);
	return 0;
}

希望此文对你有帮助。

转载于:https://www.cnblogs.com/ZiQi-pro/archive/2012/01/07/2315626.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值