2018.1.20更新。
二叉搜索树是一种,昂,很厉害的数据结构。
下面是大一上学期学c语言的代码,来自应该烧香供着的圣经《c程序设计语言》。
里面有加节点和打印树的操作,freetree是我当时自己写的。
本来我现在更新应该加个deletetree来着,但是有点懒。。姑且写一下删除的算法,就不实现了。
(后面有c++模板,敲题目可以直接用)。
deletetree删除方法:
删除的最大问题就是怕删了一个节点后它的后代们就悬空了,这时候肯定要从后代中找一个优秀的后代来继承爸爸爷爷太爷爷的位置。
我们知道一个节点的左子树是比老爸小的,右子树是比老爸大的,所以把删除节点的左子树的最大节点(也就是尽量取右边)提上去。
这样这个节点肯定和原来的要被删除的节点一样比左儿孙们都大比右儿孙们都小。(从右子树选最小的也没毛病吧)。
这里的二叉树是存储字符串的,大体结构和一般的没啥区别,就不多说了,欣赏圣经里优美的代码。
还有后面模拟的缓冲区也很漂亮。
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#define MAXWORD 1000
struct tnode//节点
{
char *s;
int count;
struct tnode *left;
struct tnode *right;
};
struct tnode *addtree(struct tnode *, char *);
void treeprint(struct tnode *);
int getword(char *, int);
void freetree(struct tnode *p);//原文没有这个函数,本来也没写,心疼一下堆栈
int main()
{
struct tnode *root = NULL;
char word[MAXWORD];
while( getword(word, MAXWORD) != EOF )
{
if(isalpha(word[0]))
root = addtree(root, word);
}
treeprint(root);
freetree(root);
return 0;
}
void treeprint(struct tnode *t)//递归打印树
{
if( t != NULL )
{
treeprint( t->left );
printf("%4d %s\n", t->count, t->s );
treeprint( t->right );
}
}
struct tnode *talloc(void)//封装malloc
{
return (struct tnode *)malloc( sizeof(struct tnode) );
}
struct tnode *addtree(struct tnode *r, char *s)//递归
{
int cond;
if( r == NULL )
{
r = talloc();
r->count = 1;
r->s = strdup(s);
r->left = r->right = NULL;
}
else if( (cond = strcmp(s, r->s)) < 0 )//cond记录比较结果
r->left = addtree( r->left, s );
else if( cond > 0)
r->right = addtree( r->right, s );
else
r->count++;//如果已经存在,计数器自增
return r;
}
void freetree(struct tnode *p)
{
if(p != NULL)
{
freetree(p->left);
freetree(p->right);
free(p->s);
free(p);
}
}
//getch和ungetch的实现,ungetch把没用的已经读入字符
//存回缓冲区,用自己定义的栈实现
int buf[BUFSIZ];
int bp = 0;
int getch()//如果栈空了,读入缓冲区的内容
{
return bp == 0?getchar():buf[--bp];
}
void ungetch(int c)
{
if( bp < BUFSIZ)
buf[bp++] = c;
else
printf("BUF IS FULL\n");
}
int getword(char *word, int n)
{
char c, *s = word;
while( isspace( c = getch() ) );
if( c != EOF ) *s++ = c;else return EOF;
if( !isalnum(c) ) { *s = '\0'; return c;}
for(; --n; s++)
if( !isalnum( *s = getch() ) )
{ungetch(*s);break;}
*s = '\0';
return word[0];//判断是否EOF
}
来自《c程序设计语言》,有改动。
昂既然更新就再加个c++模板类:
#include <cstdio>
#include <set>
using namespace std;
int main()
{
//claim
set<int> s;
//insert
s.insert(1);
s.insert(8);
s.insert(9);
s.insert(5);
//search way1
set<int>::iterator ite;
ite = s.find(9);
if( ite == s.end() )
printf("Not Found\n");
//search way2
if(s.count(1) == 0)
printf("Not Found\n");
//search way3
for(ite = s.begin(); ite != s.end(); ite++)
printf("%d\n", *ite);
//delete
s.erase(1);
return 0;
}
没上cplusplus查,应该还有一些其他操作。
来自《挑战程序设计竞赛》,有改动。