上次讲了搜索二叉树的基本算法,这次就来应用它做一些简单的问题。
一。判断单词是否拼写正确。(一个简单的字典)
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<windows.h>
typedef struct Word{ //定义字典结构体。
char word[20];
struct Word *pleft;
struct Word *pright;
}Word;
int Insert(Word **pWord,const char *word) //插入函数。
{
int r;
if(*pWord==NULL) //如果字典为空,将word插入进去即可。
{
*pWord=(Word *)malloc(sizeof(Word));
assert(*pWord);
strncpy((*pWord)->word,word,20);
(*pWord)->pleft=(*pWord)->pright=NULL;
return 0;
}
r=strncmp((*pWord)->word,word,20); //令r为将word拷贝到字典里的结果。
if(r==0) //等于0表示字典里已经有了。
{
return -1;
}
else if(r<0) //否则递归左右子树。
{
return Insert(&((*pWord)->pleft),word);
}
return Insert(&((*pWord)->pright),word);
}
int SpellRight(Word *pWord,const char *word)
{
int r;
if(pWord==NULL) //如果字典为空,则返回错误。
{
return 0;
}
r=strncmp(pWord->word,word,20);
if(r==0) //若相等,返回正确。
{
return 1;
}
else if(r<0) //否则递归左右子树即可。
{
return SpellRight(pWord->pleft,word);
}
return SpellRight(pWord->pright,word);
}
void test2()
{
char word[20];
Word *pWord = NULL;
Insert(&pWord, "Apple"); //向字典里插入两个单词。
Insert(&pWord, "Banana");
while (1) {
scanf("%s", &word); //输入要检查的单词。
if (SpellRight(pWord, word)) { //如果对的话输出正确。
printf("拼写正确\n");
}
else {
printf("拼写错误\n"); //否则输出错误。
}
}
}
二。最受欢迎的三种水果。
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<Windows.h>
typedef struct {
char fruit[20]; //水果名字。
int count; //次数。
}Report;
typedef struct Fruit{
char fruit[20];
int count;
struct Fruit *pleft;
struct Fruit *pright;
}Fruit;
int Insert(Fruit **pRoot,const char *fruit) //插入函数。
{
int r;
if(*pRoot==NULL) //若为空,直接插入。
{
*pRoot=(Fruit *)malloc(sizeof(Fruit));
assert(*pRoot);
strncpy((*pRoot)->fruit,fruit,20);
(*pRoot)->pleft=(*pRoot)->pright=NULL;
return 0;
}
r=strncmp((*pRoot)->fruit,fruit,20);
if(r==0)
{
return -1;
}
else if(r<0)
{
return Insert(&((*pRoot)->pleft),fruit);
}
return Insert(&((*pRoot)->pright),fruit);
}
Fruit *Find(Fruit *pRoot,const char *fruit) //查找函数。
{
int r;
if(pRoot==NULL) //若为空返回空。
{
return NULL;
}
r=strncmp(pRoot->fruit,fruit,20);
if(r==0) //若存在返回节点。
{
return pRoot;
}
else if(r<0)
{
return Find(pRoot->pleft,fruit);
}
return Find(pRoot->pright,fruit);
}
void InOrder(Fruit *pRoot, Report array[], int *i, int max) //遍历。
{
assert(*i < max);
if (pRoot == NULL) {
return;
}
InOrder(pRoot->pleft, array, i, max);
strncpy(array[*i].fruit, pRoot->fruit, 20);
array[*i].count = pRoot->count;
(*i)++;
// 遍历根结点
InOrder(pRoot->pright, array, i, max);
}
void AdjustDown(Report array[], int size, int parent) //向下调整法。
{
int left=2*parent+1;
int right=2*parent+2;
int max;
if(left>=size)
{
return;
}
max=left;
if(right<size && array[right].count<array[max].count)
{
max=right;
}
if(array[parent].count>array[max].count)
{
Report t = array[parent];
array[parent] = array[max];
array[max] = t;
}
else{
return;
}
AdjustDown(array,size,max);
}
void MakeHeap(Report array[],int size) //建小堆。
{
int i;
for(i=(size-2)/2;i>=0;i--)
{
AdjustDown(array,size,i);
}
}
void test3()
{
int i;
Fruit *pRoot = NULL;
Report array[100];
int size = 0;
Report heap[3];
const char * fruits[] = { //给数组里存取值。
"Apple", "Banana", "Watermelon", "Pineapple",
"Apple", "Apple", "Apple", "Banana", "Pear", "Pear",
"Orange"
};
for (i = 0; i < sizeof(fruits) / sizeof(char *); i++) { //统计每种水果次数或插入新水果。
const char * fruit = fruits[i];
Fruit *pFound = Find(pRoot, fruit);
if (pFound) {
pFound->count++;
}
else {
Insert(&pRoot, fruit);
}
}
InOrder(pRoot, array, &size, 100); //先取出三个水果刀新的数组。
for (i = 0; i < 3; i++) {
heap[i] = array[i];
}
MakeHeap(heap, 3); //将这三个建个小堆。
for (i = 3; i < size; i++) {
if (array[i].count > heap[0].count) {
heap[0] = array[i];
AdjustDown(heap, 3, 0); //如此统计出最受欢迎的三种水果。
}
}
for(i=0;i<3;i++) //打印三种水果的开头字母。
{
printf("%c ",heap[i]);
}
printf("\n");
}
以上两道题是很简单的搜索二叉树的应用,此外也包含了堆的应用,十分适合初学者掌握二叉搜索树。