Chinaunix首页 | 论坛 | 博客
  • 博客访问: 68059
  • 博文数量: 5
  • 博客积分: 1485
  • 博客等级: 上尉
  • 技术积分: 70
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-23 17:44
文章分类

全部博文(5)

文章存档

2014年(1)

2011年(2)

2010年(2)

我的朋友
最近访客

分类: C/C++

2010-12-24 19:33:47

文件:bintree.rar
大小:7KB
下载:下载
    不知道什么原因,又看到了数据结构的二叉搜索树,突然有个想法用C++模板和仿函数去实现,这样既可以锻炼下C++模板功力,又可以看看仿函数真实内幕,何乐而不为!
    既然要写就要写的清楚明白,把自己所想、所学写出(尽管自己是程序新手),让浏览或参考的人看的请明了,或指出瑕疵,或有所心得!

    1、C++模板类声明跟实现都放在头文件,故此命名为binSearchTree.h的头文件,该文件包含一个二叉搜索树节点类,一个二叉搜索树类;

    2、仿函数类放在文件cmpFunc.h中,包括string类型和内置内型的比较实现  

     3、测试数据来源,每个写的数据结构都要去测试,那必须有随机数生成接口,我把声明定义于random.h中,实现random.cpp中;其中有随机数生成的测试用例test_random.cpp

    4、、测试用例,test_tree.cpp中,最后是makefile的书写;

代码如下(附件包括所有文件可以下载):

1、仿函数类

说明:对string类型和内置类型分别实现了相应的比较函数,放在名字空间bill

/*
 * cmpFunc.h
 *
 * Created on: 2010-12-25
 * Author: Administrator
 */


#ifndef CMPFUNC_H_
#define CMPFUNC_H_

#include <cstring>

namespace bill
{
//仿函数针对string

class CmpStr{
public:
    int operator()(const std::string& str1,const std::string& str2)
    {
        return operator ()(str1.c_str(),str2.c_str());
    }
    int operator()(const char* str1,const char* str2)
    {
        return strcmp(str1,str2);
    }
};

/*仿函数模板类针对int float double*/
template<typename Class>
class Cmp{
public:
    int operator()(const Class& first,const Class& second){
        return (first - second);
    }
};
}
#endif /* CMPFUNC_H_ */

2、二叉搜索树模板类

说明:实现大部分功能插入、删除、检索,其他扩展功能请大家自行添加!

/*
 * binSearchTree.h
 *
 * Created on: 2010-12-23
 * Author: Administrator
 * 模板书写二叉搜索树
 */

#ifndef BINSEARCHTREE_H_
#define BINSEARCHTREE_H_

#include <iostream>

namespace bill {
/*二叉树节点模板类*/
template<typename Class>
class BinNode {
    public:
        BinNode(const Class& _data,BinNode<Class> *lt = NULL,BinNode<Class> *rt = NULL,BinNode<Class> *_parent = NULL)
        :data(_data),left(lt),right(rt),parent(_parent){
            count = 1;
        }
        ~BinNode(){ left = right = parent = NULL; count = 0; }
    public:
        Class data; //节点数据
        BinNode<Class> *left; //节点左孩子
        BinNode<Class> *right; //节点右孩子
        BinNode<Class> *parent; //节点父节点
        unsigned int count; //该数据的个数
};
/*二叉搜索树模板类*/
template<typename Class, typename Compare>
class BinSearchTree {
public:
    BinSearchTree() { cmp = new Compare(); root = NULL; uNodeCount = 0; }
    ~BinSearchTree(){ destroyBinTree(); }

    int insert(const Class& data);
    int remove(const Class& data);
    bool search(const Class& data);
    const Class& findMax() const; //未实现
    const Class& findMin() const; //未实现
    const Class& getRootData() const { return root->data; }
    int getNodeCount() const { return uNodeCount; }
    void Inorder() const { visitInorder(root); }//递归实现
    void visitPrevorder() const;//未实现
    void visitPostorder() const;//未实现

    void destroyBinTree() //消毁二叉搜索树
    {
        if(root != NULL)
        {
            destroyBinNode(root);
        }
        delete cmp;
    }

    BinNode<Class>* searchNodeAndParent(const Class& data,BinNode<Class>*& parent = NULL)
    {
        BinNode<Class>* pNode = root;

        while(pNode != NULL)
        {
            parent = pNode->parent;
            int nRet = (*cmp)(pNode->data,data);
            if(nRet != 0)
            {
                parent = pNode;
                if(nRet < 0)
                {
                    pNode = pNode->right;
                }
                else
                {
                    pNode = pNode->left;
                }
            }else{
                return pNode;
            }
        }
        return NULL;
    }
private:
    BinNode<Class> *root; //根节点
    unsigned int uNodeCount; //节点数目
    Compare *cmp; //比较函数
    void visitInorder(BinNode<Class> *node = NULL) const;

    BinNode<Class>* searchNode(const Class& data)//搜索数据为data的节点
    {
        BinNode<Class>* pNode;
        pNode = root;

        while(pNode != NULL)
        {
            int nRet = (*cmp)(pNode->data,data);
            if(nRet < 0)
            {
                pNode = pNode->right;
            }else if(nRet > 0)
            {
                pNode = pNode->left;
            }
            else
            {
                return pNode;
            }
        }
        return NULL;
    }
    //private functions
    void destroyBinNode(BinNode<Class> *node) //递归销毁节点
    {
        if(node->left != NULL)
        {
            destroyBinNode(node->left);
        }
        if(node->right != NULL)
        {
            destroyBinNode(node->right);
        }
        delete node;
    }
};
template<typename Class, typename Compare>
bool BinSearchTree<Class,Compare>::search(const Class& data)
{
    BinNode<Class> *pNode = searchNode(data);

    if(pNode != NULL)
    {
        return true;
    }
    else
    {
        return false;
    }
}

template<typename Class, typename Compare>
int BinSearchTree<Class,Compare>::insert(const Class& data)
{
    BinNode<Class> *pNode;
    BinNode<Class> *pParent = NULL;
    BinNode<Class> *pNewNode;

    pNode = searchNodeAndParent(data,pParent);//搜索不成功时,可能根为NULL

    pNewNode = new BinNode<Class>(data);

    if(pNewNode == NULL)
    {
        return -1; //失败
    }

    if(pNode != NULL) //已经有该数据
    {
        pNode->count++; //递增它的个数
    }
    else
    {
        if(root == NULL)
        {
            root = pNewNode;
            uNodeCount++;
        }
        else
        {
            if(pParent == NULL)
                pParent = root;
            int nRet = (*cmp)(pParent->data,data);
            if(nRet < 0)
            {
                pParent->right = pNewNode;
            }
            else
            {
                pParent->left = pNewNode;
            }
            pNewNode->parent = pParent;
            uNodeCount++;

        }
    }
    return 1;
}
template<typename Class, typename Compare>
int BinSearchTree<Class,Compare>::remove(const Class& data)
{
    BinNode<Class> *pNode;
    BinNode<Class> *pParentNode;
    BinNode<Class> *pMaxNode;
    BinNode<Class> *pParentMaxNode;
    int nRet = 0;

    if(root == NULL)
    {
        return -1;
    }

    pParentNode = NULL;
    pNode = searchNodeAndParent(data,pParentNode);

    if(pNode == NULL)
    {
        return -1; //搜索失败
    }

    /*第一种情况,pNode两字节点都不为空时*/
    if(pNode->left != NULL && pNode->right != NULL)
    {
        pMaxNode = pNode->left;
        pParentMaxNode = pNode;
        while(pMaxNode->right != NULL)
        {
            pParentMaxNode = pMaxNode;
            pMaxNode = pMaxNode->right;
        }

        pNode->data = pMaxNode->data;
        if(pMaxNode == pNode->left)
        {
            pNode->left = pMaxNode->left;
        }
        else
        {
            pParentMaxNode->right = pNode->left;
        }
        delete pMaxNode;
        return 1;
    }

    if(pNode->left != NULL)
    {
        pMaxNode = pNode->left;
    }else if(pNode->right != NULL)
    {
        pMaxNode = pNode->right;
    }

    if(pNode == root)
    {
        root = pMaxNode;
    }else{
        if(pParentNode->left == pNode)
        {
            pParentNode->left = pMaxNode;
        }
        else
        {
            pParentNode->right = pMaxNode;
        }
    }
    delete pNode;
    return 1;
}

template<typename Class, typename Compare>
void BinSearchTree<Class,Compare>::visitInorder(BinNode<Class>* node) const
{
    if(node != NULL)
    {
        visitInorder(node->left);
        std::cout<<node->data<<"["<<node->count<<"] ";
        visitInorder(node->right);
    }
}
} // namespace bill
#endif /* BINSEARCHTREE_H_ */

3、随机数生产类

一个简单测随机数生成类,见附件代码

4、测试用例与Makefile

说明:简单的测试用例以及Makefile文件编写(g++)

/*
 * tree.cpp
 *
 * Created on: 2010-12-24
 * Author: Administrator
 */
#include "binSearchTree.h"
#include <iostream>
#include "random.h"
#include "cmpFunc.h"

/*测试用例1(内置类型)*/
void TestCaseForInteger()
{
    const int size = 10000;
    bill::BinSearchTree<int,bill::Cmp<int> > binSearchTree;
    bill::Random random;
    int rand[size];
    int i = 0;
    int search_key;

    random.seed(2011);

    for(i = 0; i < size; ++i)
    {
        rand[i] = random.random(0,size);
    }

    for(i = 0; i < size; ++i)
        binSearchTree.insert(rand[i]);
    binSearchTree.Inorder();
    while(std::cin>>search_key)
    {
        if(binSearchTree.search(search_key))
        {
            binSearchTree.remove(search_key);
            //binSearchTree.Inorder();
            std::cout<<"删除成功!"<<std::endl;
        }
        else{
            std::cout<<"没有该数据,删除失败!"<<std::endl;
        }
    }
}

void TestCaseForStr()
{
    bill::BinSearchTree<std::string,bill::CmpStr> binSearchTree;
    std::string strs[] = {"libin","hello","world","liying","china","American","Japness"};

    for(int i = 0; i < 7; ++i)
        binSearchTree.insert(strs[i]);

    binSearchTree.Inorder();
}
int main(int argc, char**argv) {

    TestCaseForInteger();
    TestCaseForStr();

    return 0;
 }

#Makfile
#
# Created on: 2010-12-25
# Author: Administrator

CXX = g++
CFLAGS = -w -O2
TARGET = test_tree.exe
OBJECTS = test_tree.o random.o

all: $(TARGET)
    
$(TARGET): test_tree.o random.o
    $(CXX) $(CFLAGS) -o $@ $^
$(OBJECTS): %.o : %.cpp
    $(CXX) $(CFLAGS) -c -o $@ $<
clean:
    @rm -rf $(TARGET) *.o
dist:
    tar -zcvf bintree.tar.gz ./*

5、扩展与源代码下载

   如果写出好的分词程序,就可以配合起来实现简单的词典构建,那会更好的去测试它,更所谓英雄需要美女,不错!不过搜索引擎的词典构建常用AVL和红黑树或其他结构哈希AVL或哈希红黑树,那可能要等我有时间才去写了!

  

源代码
文件:bintree.tar.gz
大小:3KB
下载:下载

阅读(1163) | 评论(1) | 转发(0) |
0

上一篇:没有了

下一篇:欢迎大家光临寒舍

给主人留下些什么吧!~~

chinaunix网友2010-12-26 10:52:10

写的一般般!~路过....