算法之美_源代码发布(8)

本文辑录了《算法之美——隐匿在数据结构背后的语言》(电子工业出版社2016年出版)一书第8章后半部分至第9章之代码(P273~P320)。全文目录、“45个算法”目录“22个经典问题目录”,以及有奖捉虫活动详情请见如下链接:http://blog.csdn.net/baimafujinji/article/details/50484348

附录中的经典笔试、面试问题参考答案请见:

http://blog.csdn.net/baimafujinji/article/details/50484683

In general, 我不太喜欢翻开一本书(技术书),里面密密麻麻的全部都是代码。所以我也希望能够在我的书中留下更多空间去讨论原理和思路。当然,代码也很重要,所有的一切原理最终都要落实到代码上。为此我习惯于在博客中上传代码,而非是把他们全部罗列到书中去挤占篇幅。最后,我仍然建议那些有心学好算法和数据结构的同学彻底击破书中涉及到的算法原理,做到知其然更知其所以然,只有这样你才算是真正学到了东西,也只有这样,你在遇到新的编程问题时才不会束手无策。

如果你是该书的读者,强烈建议你加入算法学习群(495573865),内有更多资源等你,而你在读书中遇到的疑问也将得到我第一时间的解答。更多关注本博客,我将陆续发布该书全部源代码至本博客。

P277  利用Kruskal算法解决“道路修建问题”

#include "stdafx.h"
#include "stdio.h"
#include "stdlib.h"
#include "iostream"

using namespace std;

#define N 110

typedef struct{
	int prior;int next;
	int dis;
}Node;

Node node[N*N];
int father[N];
int find(int);
int union_(int ,int);
int MST_Kruskal();
int n,ans=0;
int cmp(const void *a,const void *b) {
	Node *x=(Node*)(a);Node *y=(Node*)(b);
	return (x->dis-y->dis);
}

int _tmain(int argc, _TCHAR* argv[])
{
	int m=0;
	int i,j,a,b,t=0;
	scanf("%d",&n);
	for(i=1;i<n+1;i++)
		for(j=1;j<n+1;j++) {
			node[t].prior=i;
			node[t].next=j;
			scanf("%d",&node[t++].dis);

		}
	scanf("%d",&m);
	for(i=1;i<N;i++)
		father[i]=-1;
	for(i=0;i<m;i++) {
		scanf("%d%d",&a,&b);
		union_(a,b);
	}
	qsort(node,n*n,sizeof(Node),cmp);
	MST_Kruskal();

	cout<<ans<<endl;

	system("PAUSE");
	return 0;
}

int MST_Kruskal() {
	int i=0,u,v;
	for(i=0;i<n*n;i++) {
			u=node[i].prior;
			v=node[i].next;
			if(find(u)!=find(v)) {
					union_(u,v);
					ans+=node[i].dis;
			}
	}
	return 0;
}

int find(int a ){
	int i,temp;
	for(i=a;father[i]>0;i=father[i]);
	while(a!=i) {
		temp=father[a];
		father[a]=i;
		a=temp;
	}
	return i;
}

int union_(int a,int b) {
	int temp,temp1=find(a),temp2=find(b);
	if(temp1==temp2) return 0;
	temp=father[temp1]+father[temp2];
         father[temp2]=temp1;
         father[temp1]=temp;
         return 1;
}

P281  Prim算法求解最小生成树

#include "stdafx.h"
#include "iostream"

using namespace std;

#define MaxNumVer 10
#define MaxWeight 100

int _tmain(int argc, _TCHAR* argv[])
{
	cout<<"请注意:"<<endl;
	cout<<"\t本程序默认的最大顶点数为10"<<endl;
	cout<<"\t边权值的取值范围是介于0到99之间"<<endl<<endl;

	int G[MaxNumVer][MaxNumVer],in[MaxNumVer]={0},path[MaxNumVer][2];
	int i,j,k,min=MaxWeight;
	int v1,v2,num,tmpValue,status=0,start=0;

	//输入图结点的数目
	while(true)
	{
		cout<<"请输入图中顶点的数目:"<<endl;
		cin>>num;
		if(num<=MaxNumVer&&num>0)
			break;
		cout<<"错误!请确认后重新输入."<<endl<<endl;
	}

	//创建图并使用邻接矩阵G来存储图
	for(j=0;j<num;j++)
		for(k=0;k<num;k++)
		{
			if(j==k)
				G[j][k]=MaxWeight;
			else if(j<k)
			{
				while(true)
				{
					cout<<"请输入边("<<j+1<<","<<k+1<<")的权值, 如果改变不存在请输入-1:"<<endl;
					cin>>tmpValue;
					if(tmpValue>=-1&&tmpValue<MaxWeight)break;
					cout<<endl<<"输入无效!请确认后重新输入."<<endl;
				}

				if(tmpValue==-1)
					tmpValue=MaxWeight;

				G[j][k]=G[k][j]=tmpValue;//矩阵是对称的
			}
		}

	for(j=0;j<num;j++)
	{
		status=0;
		for(k=0;k<num;k++)
			if(G[j][k]<MaxWeight)
			{
				status=1;
				break;
			}
		if(status==0)
			break;
	}

	//如果图是非连通的则退出程序
	if(!status){
		cout<<"无法处理,因为该图是非连通的!"<<endl;
		return -1;
	}

	//选择算法的起始点
	while(true){
		cout<<"请选择Prim算法的起始点:"<<endl;
		cin>>start;

		if(start>0 && start<=num)
			break;

		cout<<"错误!请确认后重新输入."<<endl<<endl;
	}

	//Prim算法求最小生成树
	in[start-1]=1; //标记

	for(i=0;i<num-1;i++)
	{
		for(j=0;j<num;j++)
			for(k=0;k<num;k++)
				if(G[j][k]<min&&in[j]&&(!in[k]))
				{
					v1=j;
					v2=k;
					min=G[j][k];
				}

		if(!in[v2])
		{
			path[i][0]=v1;
			path[i][1]=v2;

			//标记
			in[v1]=1;
			in[v2]=1;

			min=MaxWeight;
		}

	}

	//输出结果
	cout<<"最小生成树如下:"<<endl;
	for(i=0;i<num-1;i++)
		cout<<"("<< path[i][0]+1 <<", "<< path[i][1]+1<< ")" <<endl;

	system("PAUSE");
	return 0;
}

P288  二叉搜索树的实现


BinarySearchTree.h 文件

#ifndef BINARY_SEARCH_TREE_H_
#define BINARY_SEARCH_TREE_H_

class BinarySearchTree;

class BinaryNode
{
	int  element;
    BinaryNode *left;
    BinaryNode *right;

    BinaryNode( int theElement, BinaryNode *lt,
                BinaryNode *rt)
      : element( theElement ), left( lt ), right( rt ) { }

public:
	int getElement(){
		return element;
	}

    friend class BinarySearchTree;
};

class BinarySearchTree
{
  public:
    BinarySearchTree( );
    virtual ~BinarySearchTree( );

    BinaryNode * findMin( ) const;
    BinaryNode * findMax( ) const;
    BinaryNode * find( int x ) const;
    bool isEmpty( ) const;

    void makeEmpty( );
    void insert( int x );
    void remove( int x );
    void removeMin( );

    const BinarySearchTree & operator=( const BinarySearchTree & rhs );

  protected:
    BinaryNode *root;

    virtual void insert( int x, BinaryNode * & t ) const;
    virtual void remove( int x, BinaryNode * & t ) const;
    virtual void removeMin( BinaryNode * & t ) const;
    BinaryNode * findMin( BinaryNode *t ) const;
    BinaryNode * findMax( BinaryNode *t ) const;
    BinaryNode * find( int x, BinaryNode *t ) const;
    void makeEmpty( BinaryNode * & t ) const;
    BinaryNode * clone( BinaryNode *t ) const;
};

#endif

BinarySearchTree.cpp 文件

#include "BinarySearchTree.h"
#include <iostream>
#include <cstddef>

using namespace std;

// Construct the tree.
BinarySearchTree::BinarySearchTree( ) : root( NULL )
{
}

// Destructor for the tree.
BinarySearchTree::~BinarySearchTree( )
{
    makeEmpty( );
}

// Insert x into the tree;
void BinarySearchTree::insert( int x )
{
    insert( x, root );
}

// Remove x from the tree.
void BinarySearchTree::remove( int x )
{
    remove( x, root );
}

// Remove minimum item from the tree.
void BinarySearchTree::removeMin( )
{
    removeMin( root );
}

BinaryNode * BinarySearchTree::findMin( ) const
{
    return findMin( root );
}

BinaryNode * BinarySearchTree::findMax( ) const
{
    return findMax( root );
}

// Find item x in the tree.
BinaryNode * BinarySearchTree::find( int x ) const
{
    return find( x, root );
}

// Make the tree logically empty.
void BinarySearchTree::makeEmpty( )
{
    makeEmpty( root );
}

// Test if the tree is logically empty.
// Return true if empty, false otherwise.
bool BinarySearchTree::isEmpty( ) const
{
    return root == NULL;
}

// Deep copy.
const BinarySearchTree &
BinarySearchTree::
operator=( const BinarySearchTree & rhs )
{
    if( this != &rhs )
    {
        makeEmpty( );
        root = clone( rhs.root );
    }
    return *this;
}

void BinarySearchTree::
insert( int x, BinaryNode * & t ) const
{
    if( t == NULL )
        t = new BinaryNode( x, NULL, NULL );
    else if( x < t->element )
        insert( x, t->left );
    else if( t->element < x )
        insert( x, t->right );
    else
    {
    	cout<<"ERROR!! Duplicate Element."<<endl;
	}
}

void BinarySearchTree::
remove( int x, BinaryNode * & t ) const
{
    if( t == NULL )
    {
    	cout<<"This node does not exist!!"<<endl;
    	return;
	}

    if( x < t->element )
        remove( x, t->left );
    else if( t->element < x )
        remove( x, t->right );
    else if( t->left != NULL && t->right != NULL ) // Two children
    {
        t->element = findMin( t->right )->element;
        removeMin( t->right );                   // Remove minimum
    }
    else
    {
        BinaryNode *oldNode = t;
        t = ( t->left != NULL ) ? t->left : t->right;  // Reroot t
        delete oldNode;                         // delete old root
    }
}

void BinarySearchTree::removeMin( BinaryNode * & t ) const
{
    if( t == NULL )
    {
    	cout<<"Empty Tree!!"<<endl;
    	return;
	}
    else if( t->left != NULL )
        removeMin( t->left );
    else
    {
        BinaryNode *tmp = t;
        t = t->right;
        delete tmp;
    }
}

BinaryNode * BinarySearchTree::findMin( BinaryNode *t ) const
{
    if( t != NULL )
        while( t->left != NULL )
            t = t->left;

    return t;
}

BinaryNode* BinarySearchTree::findMax( BinaryNode *t ) const
{
    if( t != NULL )
        while( t->right != NULL )
            t = t->right;

    return t;
}

BinaryNode * BinarySearchTree::
find( int x, BinaryNode *t ) const
{
    while( t != NULL )
        if( x < t->element )
            t = t->left;
        else if( t->element < x )
            t = t->right;
        else
            return t;    // Match

    return NULL;         // Not found
}

void BinarySearchTree::makeEmpty( BinaryNode * & t ) const
{
    if( t != NULL )
    {
        makeEmpty( t->left );
        makeEmpty( t->right );
        delete t;
    }
    t = NULL;
}

// Internal method to clone subtree.
BinaryNode * BinarySearchTree::clone( BinaryNode * t ) const
{
    if( t == NULL )
        return NULL;
    else
        return new BinaryNode( t->element, clone( t->left ), clone( t->right ));
}

一个测试程序

#include <iostream>
#include "BinarySearchTree.h"

using namespace std;

int main( )
{
	BinarySearchTree t;
	t.insert(21);
	t.insert(12);
	t.insert(0);
	t.insert(35);
	t.insert(15);
	t.insert(36);
	t.insert(14);

	cout<< (t.findMax())->getElement()<<endl;
	cout<< (t.findMin())->getElement()<<endl;
	cout<< (t.find(35)) ->getElement()<<endl;

	t.remove(35);
	if(t.find(35)==NULL)
		cout<<"This node does not exist!!"<<endl;

	t.makeEmpty();
		cout<<t.isEmpty()<<endl;

    return 0;
}

P300:  AVL树的实现

avlnode.h文件

#ifndef AVLNODE_H
#define AVLNODE_H

#include <iostream>

using namespace std;

template <class T> class AvlTree; //声明AvlTree类

template <class T>
class AvlNode{

	T data;					//关键码
	AvlNode *leftChild;		//左孩子
	AvlNode *rightChild;	//右孩子
	int balance;			//平衡因子

public:

	//构造函数
	AvlNode():left(NULL),right(NULL),balance(0){};

	AvlNode(const T& e,AvlNode<T> *lt = NULL,AvlNode<T> *rt = NULL)
		:data(e),leftChild(lt),rightChild(rt),balance(0){};

	int getBalance() const
	{
		return balance;
	}
	AvlNode<T>* getLeftChild() const
	{
		return leftChild;
	}
	AvlNode<T>* getRightChild() const
	{
		return rightChild;
	}
	T getData() const
	{
		return data;
	}

	friend class AvlTree<T>;
};
#endif

avltree.h文件

#include "avlnode.h"

template <class T>
class AvlTree{

	AvlNode<T> *root;

	bool Insert(AvlNode<T> *& rt,T x, bool &taller);
	bool Remove(AvlNode<T> *& rt,T x, bool &shorter);

	void RotateLeft(AvlNode<T> * &node);	//左旋函数
	void RotateRight(AvlNode<T> * &node);	//右旋函数

	void RightBalanceAfterInsert(AvlNode<T> * &sRoot, bool &taller);
	void LeftBalanceAfterInsert(AvlNode<T> * &sRoot, bool &taller);
	void RightBalanceAfterDelete(AvlNode<T> * &sRoot, bool &shorter);
	void LeftBalanceAfterDelete(AvlNode<T> * &sRoot, bool &shorter);

public:

	AvlTree():root(NULL){}
	AvlNode<T>* getRoot() const
	{
		return root;
	}

	bool Insert(T x)
	{
		bool taller = false;
		return Insert(root, x, taller );
	}

	bool Remove(T x)
	{
		bool shorter = false;
		return Remove(root, x, shorter);
	}

	//输出树形结构
	void DisplayTree(AvlNode<T> *t,int layer) const;
};

template <typename T>
void AvlTree<T>::RotateLeft(AvlNode<T> * & node)
{
     if( (node == NULL) || (node->rightChild == NULL) ) return;

     AvlNode<T> * tmpNode = new AvlNode<T>(node->data);
     if(tmpNode == NULL ) return;

     tmpNode->leftChild = node->leftChild;
     node->leftChild = tmpNode;
     tmpNode->rightChild = node->rightChild->leftChild;

     AvlNode<T> *toDelete = node->rightChild;
     node->data = toDelete->data;
     node->rightChild = toDelete->rightChild;

     delete toDelete;
}

template <typename T>
void AvlTree<T>::RotateRight(AvlNode<T> * & node)
{
     if( (node == NULL) || (node->leftChild == NULL) ) return;

     AvlNode<T> *tmpNode = new AvlNode<T>(node->data);
     if(tmpNode == NULL ) return;

     tmpNode->rightChild = node->rightChild;
     node->rightChild = tmpNode;
     tmpNode->leftChild = node->leftChild->rightChild;

     AvlNode<T> *toDelete = node->leftChild;
     node->data = toDelete->data;
     node->leftChild = toDelete->leftChild;

     delete toDelete;
}

//如果插入节点后, rt的右高度增加, 则调用此函数进行平衡化
template <typename T>
void AvlTree<T>::RightBalanceAfterInsert(AvlNode<T> *&sRoot,bool &taller)
{
    if( (sRoot == NULL) || (sRoot->rightChild == NULL) ) return;
    AvlNode<T> *rightsub = sRoot->rightChild,*leftsub;
    switch(rightsub->balance){
        case 1:
            sRoot->balance = rightsub->balance = 0;
            RotateLeft(sRoot);
            taller = false; break;
        case 0:
            cout<<"树已经平衡化."<<endl; break;
        case -1:
            leftsub = rightsub->leftChild;
            switch(leftsub->balance){
                case 1:
                    sRoot->balance = -1; rightsub->balance = 0; break;
                case 0:
                    sRoot->balance = rightsub->balance = 0; break;
                case -1:
                    sRoot->balance = 0; rightsub->balance = 1; break;
            }
            leftsub->balance = 0;
            RotateRight(rightsub);
            RotateLeft(sRoot);
            taller = false; break;
    }
}

//如果插入节点后, rt的左高度增加, 则调用此函数进行平衡化
template <typename T>
void AvlTree<T>::LeftBalanceAfterInsert(AvlNode<T> *&sRoot,bool &taller)
{
    AvlNode<T> *leftsub = sRoot->leftChild,*rightsub;
    switch(leftsub->balance){
        case -1:
            sRoot->balance = leftsub->balance = 0;
            RotateRight(sRoot);
            taller = false; break;
        case 0:
            cout<<"树已经平衡化."<<endl; break;
        case 1:
            rightsub = leftsub->rightChild;
            switch(rightsub->balance){
                case -1:
                    sRoot->balance = 1; leftsub->balance = 0; break;
                case 0:
                    sRoot->balance = leftsub->balance = 0; break;
                case 1:
                    sRoot->balance = 0; leftsub->balance = -1; break;
            }
            rightsub->balance = 0;
            RotateLeft(leftsub);
            RotateRight(sRoot);
            taller = false; break;
    }
}

//如果删除节点后, rt的左高度减少, 则调用此函数进行平衡化
template <typename T>
void AvlTree<T>::RightBalanceAfterDelete(AvlNode<T> * &sRoot,bool &shorter)
{
    AvlNode<T> *rightsub = sRoot->rightChild,*leftsub;
    switch(rightsub->balance){
        case 1: sRoot->balance = sRoot->balance = 0; RotateLeft(sRoot); break;
        case 0: sRoot->balance = 0; rightsub->balance = -1; RotateLeft(sRoot); break;
        case -1:
            leftsub = rightsub->leftChild;
            switch(leftsub->balance){
                case -1: sRoot->balance = 0; rightsub->balance = 1; break;
                case 0: sRoot->balance = rightsub->balance = 0; break;
                case 1: sRoot->balance = -1; rightsub->balance = 0; break;
            }
            leftsub->balance = 0;
            RotateRight(rightsub);
            RotateLeft(sRoot);
            shorter = false; break;
    }
}

//如果删除节结点后, rt的右高度减少, 则调用此函数进行平衡化
template <typename T>
void AvlTree<T>::LeftBalanceAfterDelete(AvlNode<T> * &sRoot,bool &shorter)
{
    AvlNode<T> *leftsub = sRoot->leftChild,*rightsub;
    switch(leftsub->balance){
        case 1: sRoot->balance = sRoot->balance = 0; RotateRight(sRoot); break;
        case 0: sRoot->balance = 0; leftsub->balance = -1; RotateRight(sRoot); break;
        case -1:
            rightsub = leftsub->rightChild;
            switch(rightsub->balance){
                case -1: sRoot->balance = 0; leftsub->balance = 1; break;
                case 0: sRoot->balance = leftsub->balance = 0; break;
                case 1: sRoot->balance = -1; leftsub->balance = 0; break;
            }
            rightsub->balance = 0;
            RotateLeft(leftsub);
            RotateRight(sRoot);
            shorter = false; break;
    }
}

//插入值为x的结点, 实现方式采用递归
template <typename T>
bool AvlTree<T>::Insert(AvlNode<T> *& rt, T x, bool &taller)
{
    bool success;

	//递归函数的"基本条件"
    if ( rt == NULL )
	{
       rt = new AvlNode<T>(x);
       success = rt != NULL ? true : false;
       if ( success ) taller = true;
    }
	//如果x的值小于rt的关键码
    else if ( x < rt->data )
	{
       //Insert的递归调用,从rt的左子树寻找合适的位置插入
       success = Insert ( rt->leftChild, x, taller );

       if ( taller ){//如果插入后使得rt的左高度增加
             switch ( rt->balance ) {
                case -1 : LeftBalanceAfterInsert( rt, taller ); break;
                case 0 :  rt->balance = -1; break;
                case 1 :  rt->balance = 0;  taller = false; break;
            }
        }
    }
	//如果x的值大于rt的关键码
    else if ( x > rt->data )
	{
       //Insert的递归调用,从rt的右子树寻找合适的位置插入
       success = Insert ( rt->rightChild, x, taller );

       if ( taller ){//如果插入后使得rt的右高度增加
          switch ( rt->balance ) {
            case -1:
				rt->balance = 0;
				taller = false;
				break;
            case 0 :
				rt->balance = 1;
				break;
            case 1 :
				RightBalanceAfterInsert(rt, taller);
				break;
        }
     }
    }
    return success;
}

//删除值为x的结点, 实现方式采用递归
template <typename T>
bool AvlTree<T>::Remove(AvlNode<T> *& rt, T x, bool &shorter)
{
    bool success = false;
    if(rt == NULL) return false;

	//如果rt就是要删除的结点
    if(x == rt->data) {
        if(rt->leftChild != NULL && rt->rightChild != NULL)
		{

            //寻找rt的中序遍历的前驱结点,用r表示
            AvlNode<T> *r = rt->leftChild;
            while(r->rightChild != NULL) {
                 r = r->rightChild;
            }

            //交换rt和r的值
            T temp = rt->data;
            rt->data = r->data;
            r->data = temp;

            //递归函数, 从rt的左子树中删除关键码为x的结点
            success = Remove(rt->leftChild, x, shorter);
            if(shorter) {//如果删除后引起rt的左高度减少
                switch(rt->balance) {
                    case -1: rt->balance = 0; break;
                    case 0 : rt->balance = 1; shorter = 0; break;
                    case 1 : RightBalanceAfterDelete(rt, shorter);break;
                }
            }
        }
        else {//rt最多只有一个子女,这是递归的出口
             AvlNode<T> *p = rt;
             rt = rt->leftChild != NULL ? rt->leftChild : rt->rightChild;
             delete p;
             success = true;
             shorter = true;
        }
    }

    else if(x < rt->data) {
        //递归函数调用,从rt的左子树中删除关键码为x的结点
        success = Remove(rt->leftChild, x, shorter);
        if(shorter) {//如果删除后引起rt的左高度减少
            switch(rt->balance) {
                case -1: rt->balance = 0; break;
                case 0 : rt->balance = 1; shorter = 0; break;
                case 1 : RightBalanceAfterDelete(rt, shorter); break;
            }
        }
    }

    else if(x > rt->data) {
        //递归函数调用,从rt的右子树中删除关键码为x的结点
        success = Remove(rt->rightChild, x, shorter);
        if(shorter) {//如果删除后引起sRoot的右高度减少
            switch(rt->balance) {
                case -1: LeftBalanceAfterDelete(rt, shorter); break;
                case 0 : rt->balance = -1; shorter = 0; break;
                case 1 : rt->balance = 0; break;
            }
        }
    }
    return success;
}

template <typename T>
void AvlTree<T>::DisplayTree(AvlNode<T> *t,int layer) const
{
    if(t == NULL)
		return;
    if(t->rightChild)
		DisplayTree(t->rightChild, layer+1);
    for(int i =0;i<layer;i++)
		cout<<"    ";
    cout<<t->data<<endl;
    if(t->leftChild)
		DisplayTree(t->leftChild,layer+1);
}

测试程序 main.cpp

#include <conio.h>
#include <iostream>
#include "avltree.h"

using namespace std;

int main(int argc, char** argv) {

	AvlTree<int> tree;

	tree.Insert(21);
	tree.Insert(12);
	tree.Insert(35);
	tree.Insert(0);
	tree.Insert(15);
	tree.Insert(36);
	tree.Insert(14);
	tree.Insert(7);
	tree.Insert(28);
	tree.Insert(9);

    tree.DisplayTree(tree.getRoot(), 0);

	while(true)
	{
		int number;
		cout<<"请输入要删除的结点:"<<endl;
		cin>>number;
		tree.Remove(number);
		cout<<"删除后的树为:"<<endl;
		tree.DisplayTree(tree.getRoot(), 0);

		cout<<"按ESC退出, 或按任意键继续!"<<endl;
		int order=getch();
		if (order ==27)
		{
			break;
		}
    }

	return 0;
}

P314:  红黑树的实现

RedBlackTree.h文件

template <typename T>
class Node{
    public:
        bool color;			//RED - 1, BLACK - 0
        T key;				// 关键字(键值)
        Node *left;			// 左孩子
        Node *right;		// 右孩子
        Node *parent;		// 父结点

        Node(T value, bool c, Node *p, Node *l, Node *r):
            key(value),color(c),parent(),left(l),right(r) {}
};

template <typename T>
class RBTree {
    private:
        Node<T> *root;    // 根结点

    public:
        RBTree();
        ~RBTree();

        Node<T>* FindElement(T key);

        T GetMin();
        T GetMax();

        void RBTInsert(T key);
        //void RBTRemove(T key);
        void Destroy();

    private:

        Node<T>* FindElement(Node<T>* x, T key) const;

        Node<T>* GetMin(Node<T>* tree);
        Node<T>* GetMax(Node<T>* tree);

        void LeftRotate(Node<T>* &root, Node<T>* x);
        void RightRotate(Node<T>* &root, Node<T>* y);

        void RBTInsert(Node<T>* &root, Node<T>* node);
        void RBTInsertFixUp(Node<T>* &root, Node<T>* node);
        //void RBTRemove(Node<T>* &root, Node<T> *node);
        //void RBTRemoveFixUp(Node<T>* &root, Node<T> *node, Node<T> *parent);

        void Destroy(Node<T>* &tree);
};

//构造函数
template <typename T>
RBTree<T>::RBTree()
{
    root = NULL;
}

//析构函数
template <typename T>
RBTree<T>::~RBTree()
{
    Destroy();
}

//销毁红黑树
template <typename T>
void RBTree<T>::Destroy(Node<T>* &tree)
{
    if (tree==NULL)
        return ;

    if (tree->left != NULL)
        return destroy(tree->left);
    if (tree->right != NULL)
        return destroy(tree->right);

    delete tree;
    tree=NULL;
}

template <typename T>
void RBTree<T>::Destroy()
{
    Destroy(root);
}

template <typename T>
Node<T>* RBTree<T>::FindElement(Node<T>* x, T key) const
{
    if (x==NULL || x->key==key)
        return x;

    if (key < x->key)
        return FindElement(x->left, key);
    else
        return FindElement(x->right, key);
}

//在树中查找一个元素
template <typename T>
Node<T>* RBTree<T>::FindElement(T key)
{
    FindElement(root, key);
}

template <typename T>
Node<T>* RBTree<T>::GetMin(Node<T>* tree)
{
    if (tree == NULL)
        return NULL;

    while(tree->left != NULL)
        tree = tree->left;
    return tree;
}

//取得树中最小的关键码
template <typename T>
T RBTree<T>::GetMin()
{
    Node<T> *p = GetMin(root);
    if (p != NULL)
        return p->key;

    return (T)NULL;
}

template <typename T>
Node<T>* RBTree<T>::GetMax(Node<T>* tree)
{
    if (tree == NULL)
        return NULL;

    while(tree->right != NULL)
        tree = tree->right;
    return tree;
}

//取得树中最大的关键码
template <typename T>
T RBTree<T>::GetMax()
{
    Node<T> *p = GetMax(root);
    if (p != NULL)
        return p->key;

    return (T)NULL;
}

//左旋函数
template <typename T>
void RBTree<T>::LeftRotate(Node<T>* &root, Node<T>* x)
{
    Node<T> *y = x->right;

    x->right = y->left;
    if (y->left != NULL)
        y->left->parent = x;

    y->parent = x->parent;

    if (x->parent == NULL)
    {
        root = y;
    }
    else
    {
        if (x->parent->left == x)
            x->parent->left = y;
        else
            x->parent->right = y;
    }

    y->left = x;
    x->parent = y;
}

//右旋函数
template <typename T>
void RBTree<T>::RightRotate(Node<T>* &root, Node<T>* y)
{
    Node<T> *x = y->left;

    y->left = x->right;
    if (x->right != NULL)
        x->right->parent = y;

    x->parent = y->parent;

    if (y->parent == NULL)
    {
        root = x;
    }
    else
    {
        if (y == y->parent->right)
            y->parent->right = x;
        else
            y->parent->left = x;
    }

    x->right = y;
    y->parent = x;
}

//插入结点后调整树结构以保持红黑性质
template <typename T>
void RBTree<T>::RBTInsertFixUp(Node<T>* &root, Node<T>* node)
{
    Node<T> *parent, *gparent;

    while ((parent = node->parent) && (parent->color==1))
    {
        gparent = node->parent;

        if (parent == gparent->left)
        {
            {
                Node<T> *uncle = gparent->right;
                if (uncle && (uncle->color==1))
                {
                    do { uncle->color = 0; } while (0);
                    do { parent->color = 0; } while (0);
                    do { gparent->color = 1; } while (0);
                    node = gparent;
                    continue;
                }
            }

            if (parent->right == node)
            {
                Node<T> *tmp;
                LeftRotate(root, parent);
                tmp = parent;
                parent = node;
                node = tmp;
            }

            do { parent->color = 0; } while (0);
            do { gparent->color = 1; } while (0);
            RightRotate(root, gparent);
        }
        else
        {
            {
                Node<T> *uncle = gparent->left;
                if (uncle && (uncle->color == 1))
                {
                    do { uncle->color = 0; } while (0);
                    do { parent->color = 0; } while (0);
                    do { gparent->color = 1; } while (0);
                    node = gparent;
                    continue;
                }
            }

            if (parent->left == node)
            {
                Node<T> *tmp;
                RightRotate(root, parent);
                tmp = parent;
                parent = node;
                node = tmp;
            }

            do { parent->color = 0; } while (0);
            do { gparent->color = 1; } while (0);
            LeftRotate(root, gparent);
        }
    }

    do { root->color = 0; } while (0);
}

//结点插入函数
template <typename T>
void RBTree<T>::RBTInsert(Node<T>* &root, Node<T>* node)
{
    Node<T> *y = NULL;
    Node<T> *x = root;

    while (x != NULL)
    {
        y = x;
        if (node->key < x->key)
            x = x->left;
        else
            x = x->right;
    }

    node->parent = y;
    if (y!=NULL)
    {
        if (node->key < y->key)
            y->left = node;
        else
            y->right = node;
    }
    else
        root = node;

    node->color = 1;
    RBTInsertFixUp(root, node);
}

template <typename T>
void RBTree<T>::RBTInsert(T key)
{
    Node<T> *z=NULL;

    if ((z=new Node<T>(key,0,NULL,NULL,NULL)) == NULL)
        return ;

    RBTInsert(root, z);
}

一个测试程序

#include <iostream>
#include "RedBlackTree.h"

using namespace std;

int main(int argc, char** argv) {

	int a[]= {12, 15, 16, 17, 21, 22, 23, 30, 35};
	int length = (sizeof(a)) / (sizeof(a[0])) ;

	RBTree<int>* tree=new RBTree<int>();
	for(int i=0; i<length; i++)
		tree->RBTInsert(a[i]);

	cout<<tree->GetMin()<<endl;
	cout<<tree->GetMax()<<endl;

	return 0;
}

P317:  Trie树的实现

特别说明:如果编译环境是DEV C++,需要把书中的头文件包含从<string>改为<cstring>,如下代码即采用这种方式。在Visual Studio 2013中,仍然可以按原书中那样用回头文件<string>。但是VS会给出下面的错误提示:

error C4996: ‘strcpy‘: This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

此时的解决办法可以参见:http://jingyan.baidu.com/article/49711c616b8a1ffa441b7cdc.html

#include <iostream>
#include <cstring>

using namespace std;

const int num_chars = 26;

class Trie {

protected:
	struct Trie_node {
		char* word;		//存储的字符
		Trie_node* branch[num_chars];
		Trie_node();
    };
    Trie_node* root;

public:
	Trie();
	int search(const char* word) const;	//查找字符
	int insert(const char* word);	//插入字符
	int remove(const char* word);
	void printall(char *pre, Trie_node *p);	//打印所有字符
	void printpre(char *pre);		//打印符合前缀的字符
};

Trie::Trie():root(NULL)
{
}

Trie::Trie_node::Trie_node()
{
	word = NULL;
	for (int i=0; i<num_chars; ++i)		//重新释放Tire树
		branch[i] = NULL;
}

int Trie::search(const char* word) const
{
	char char_code;
	Trie_node *location = root;
	while( location!=NULL && *word!=0 )
	{//逐级查找标志位
		if (*word>=‘A‘ && *word<=‘Z‘)
			char_code = *word-‘A‘;
		else if (*word>=‘a‘ && *word<=‘z‘)
			char_code = *word-‘a‘;
		else
			return 0;
		location = location->branch[char_code];
		word++;
	}

	if (location != NULL && location->word != NULL)
		return 1;
	else
		return 0;		//没有找到
}

int Trie::insert(const char* word)
{
	cout<<"插入"<<word<<endl;
	int result = 1;
	if ( root == NULL ) root = new Trie_node;
	char char_code;
	Trie_node *location = root;

	while( location!=NULL && *word!=0)
	{	//通过标志位查找
		if (*word>=‘A‘ && *word<=‘Z‘)
			char_code = *word-‘A‘;
		else if (*word>=‘a‘ && *word<=‘z‘)
			char_code = *word-‘a‘;
		else
			return 0;	//没有找到合适位置插入失败
		if( location->branch[char_code] == NULL )
			location->branch[char_code] = new Trie_node;
		location = location->branch[char_code];
		word++;
	}

	if (location->word != NULL)
		result = 0;
	else
	{
		location->word = new char[strlen(word)+1];
		strcpy(location->word, word);
	}
	return result;
}

int Trie::remove(const char* word)
{
	cout<<"删除"<<word<<endl;
	int result = 1;
	char char_code;
	Trie_node *location = root;

	while( location!=NULL && *word!=0)
	{
		if (*word>=‘A‘ && *word<=‘Z‘)
			char_code = *word-‘A‘;
		else if (*word>=‘a‘ && *word<=‘z‘)
			char_code = *word-‘a‘;
		else
			return 0;
		location = location->branch[char_code];	//删除前缀,修改标识
		word++;
	}

	if (location)
	{
		delete location->word;
		location->word = NULL;
	}
	else
		result = 0;	//删除失败

	return result;
}

//对树进行全部结点,前缀打印
void Trie::printall(char *pre, Trie_node *p)
{
	if (p->word != NULL) {
		cout<<pre<<endl;
	}

	for (int i=0; i<num_chars; ++i)
	{
		if (p->branch[i] != NULL)
		{
			char ch = ‘a‘ + i;
			char *prestr = new char[strlen(pre)+2];
			sprintf(prestr, "%s%c", pre, ch);
			printall(prestr, p->branch[i]);
			delete [] prestr;		//释放内存
		}
	}
}

void Trie::printpre(char *pre)
{
    char char_code;
    char *p = pre;
    Trie_node *location = root;

    while( location!=NULL && *pre!=0 )
	{		//判断是否符合前缀
		if (*pre>=‘A‘ && *pre<=‘Z‘)
			char_code = *pre-‘A‘;
		else if (*pre>=‘a‘ && *pre<=‘z‘)
			char_code = *pre-‘a‘;
		else
			return;		//非法字符
		location = location->branch[char_code];
		pre++;
	}
	if (location != NULL)
		printall(p, location);
	return;
}

int main(int argc, char** argv) {

	Trie t;
	t.insert("blue");
	t.insert("blur");
	t.insert("car");
	t.insert("cat");
	t.insert("caw");
	t.insert("coin");
	t.insert("coim");
	t.remove("coim");
	cout<<endl;

	cout<<"打印树中所有结点"<<endl;
	t.printpre("");
	cout<<endl;

	cout<<"开始查找"<<"cat"<<endl;
	if (t.search("cat"))
		cout<<"cat"<<" was found."<<endl;
	else
		cout<<"cat"<<" was not found."<<endl;

	cout<<"打印前缀为ca的单词:"<<endl;
	t.printpre("ca");

	return 0;
}


内容简介:探秘算法世界,求索数据结构之道;汇集经典问题,畅享编程技法之趣;点拨求职热点,敲开业界名企之门。本书围绕算法与数据结构这个话题,循序渐进、深入浅出地介绍了现代计算机技术中常用的四十余个经典算法,以及回溯法、分治法、贪婪法和动态规划等算法设计思想。在此过程中,本书也系统地讲解了链表(包括单向链表、单向循环链表和双向循环链表)、栈、队列(包括普通队列和优先级队列)、树(包括二叉树、哈夫曼树、堆、红黑树、AVL树和字典树)、图、集合(包括不相交集)与字典等常用数据结构。同时,通过对二十二个经典问题(包括约瑟夫环问题、汉诺塔问题、八皇后问题和骑士周游问题等)的讲解,逐步揭开隐匿在数据结构背后的算法原理,力图帮助读者夯实知识储备,激活思维技巧,并最终冲破阻碍编程能力提升的重重藩篱。辅有完整的C++源代码,并穿插介绍了STL中的各种容器。

网上书店:

China-pub中国互动出版网:http://product.china-pub.com/4911922

当当网:http://product.dangdang.com/23851244.html

亚马逊:http://www.amazon.cn/%E7%AE%97%E6%B3%95%E4%B9%8B%E7%BE%8E-%E9%9A%90%E5%8C%BF%E5%9C%A8%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E8%83%8C%E5%90%8E%E7%9A%84%E5%8E%9F%E7%90%86-%E5%B7%A6%E9%A3%9E/dp/B01AGNUIE8/ref=sr_1_8?ie=UTF8&qid=1453527399&sr=8-8&keywords=%E5%B7%A6%E9%A3%9E

时间: 2024-10-06 00:17:03

算法之美_源代码发布(8)的相关文章

算法之美_源代码发布(11)——完结篇

本文辑录了<算法之美--隐匿在数据结构背后的语言(C++版)>(电子工业出版社2016年出版)一书第11章之代码(P375~P406).全文目录."45个算法"目录."22个经典问题目录",以及有奖捉虫活动详情请见如下链接:http://blog.csdn.net/baimafujinji/article/details/50484348 附录中的经典笔试.面试问题参考答案请见: http://blog.csdn.net/baimafujinji/art

算法之美_源代码发布(5)

本文辑录了<算法之美--隐匿在数据结构背后的语言>(电子工业出版社2016年出版)一书第5~6章之代码(P149~P183).全文目录."45个算法"目录."22个经典问题目录",以及有奖捉虫活动详情请见如下链接:http://blog.csdn.net/baimafujinji/article/details/50484348 附录中的经典笔试.面试问题参考答案请见: http://blog.csdn.net/baimafujinji/article/

算法之美_源代码发布(3)

本文辑录了<算法之美--隐匿在数据结构背后的语言>(电子工业出版社2016年出版)一书第4章之代码(P91~P117).全文目录."45个算法"目录."22个经典问题目录",以及有奖捉虫活动详情请见如下链接:http://blog.csdn.net/baimafujinji/article/details/50484348 附录中的经典笔试.面试问题参考答案请见: http://blog.csdn.net/baimafujinji/article/det

算法之美_源代码发布(10)

本文辑录了<算法之美--隐匿在数据结构背后的语言>(电子工业出版社2016年出版)一书第10章后半部分之代码(P358~P374).全文目录."45个算法"目录."22个经典问题目录",以及有奖捉虫活动详情请见如下链接:http://blog.csdn.net/baimafujinji/article/details/50484348 附录中的经典笔试.面试问题参考答案请见: http://blog.csdn.net/baimafujinji/artic

算法之美_源代码发布(6)

本文辑录了<算法之美--隐匿在数据结构背后的语言>(电子工业出版社2016年出版)一书第7章之代码(P184~P230).全文目录."45个算法"目录."22个经典问题目录",以及有奖捉虫活动详情请见如下链接:http://blog.csdn.net/baimafujinji/article/details/50484348 附录中的经典笔试.面试问题参考答案请见: http://blog.csdn.net/baimafujinji/article/de

算法之美_源代码发布(1)

本文辑录了<算法之美--隐匿在数据结构背后的语言>(电子工业出版社2016年出版)一书第1~2章之代码(P1~P61).全文目录."45个算法"目录."22个经典问题目录",以及有奖捉虫活动详情请见如下链接:http://blog.csdn.net/baimafujinji/article/details/50484348 附录中的经典笔试.面试问题参考答案请见: http://blog.csdn.net/baimafujinji/article/det

算法之美_源码公布(1)

本文辑录了<算法之美--隐匿在数据结构背后的语言>(电子工业出版社2016年出版)一书第1~2章之代码(P1~P61).全文文件夹."45个算法"文件夹."22个经典问题文件夹",以及有奖捉虫活动详情请见例如以下链接:http://blog.csdn.net/baimafujinji/article/details/50484348 附录中的经典笔试.面试问题參考答案请见: http://blog.csdn.net/baimafujinji/articl

监督学习算法_k-近邻(kNN)分类算法_源代码

因为自己想学着去写机器学习的源码,所以我最近在学习<机器学习实战>这本书. <机器学习实战>是利用Python2完成的机器学习算法的源代码,并利用机器学习方法来对实际问题进行分析与处理. (<机器学习实战>豆瓣读书网址:https://book.douban.com/subject/24703171/) 以下内容是我通过学习<机器学习实战>,以及我对k-近邻(kNN)分类算法的理解,所总结整理出的内容,其中kNN分类算法的源码为Python3的代码,希望大家

算法之美隆重上市欢迎关注(更有三重好礼)

探秘算法世界,求索数据结构之道: 汇集经典问题,畅享编程技法之趣: 点拨求职热点,敲开业界名企之门. 内容简介:本书围绕算法与数据结构这个话题,循序渐进.深入浅出地介绍了现代计算机技术中常用的四十余个经典算法,以及回溯法.分治法.贪婪法和动态规划等算法设计思想.在此过程中,本书也系统地讲解了链表(包括单向链表.单向循环链表和双向循环链表).栈.队列(包括普通队列和优先级队列).树(包括二叉树.哈夫曼树.堆.红黑树.AVL树和字典树).图.集合(包括不相交集)与字典等常用数据结构.同时,通过对二十