zoukankan      html  css  js  c++  java
  • 算法之美_源码公布(5)

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

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

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


    In general。 我不太喜欢翻开一本书(技术书),里面密密麻麻的所有都是代码。所以我也希望可以在我的书中留下很多其它空间去讨论原理。当然,代码也非常重要。所有的一切原理终于都要落实到代码上。为此我习惯于在博客中上传代码。而非是把他们所有罗列到书中去挤占篇幅。


    假设你是该书的读者,强烈建议你加入算法学习群(495573865)。内有很多其它资源等你,而你在读书中遇到的疑问也将得到我第一时间的解答。

    很多其它关注本博客,我将陆续公布该书所有源码至本博客。


    P149:优先级队列的实现


    template <class T>
    class PriQueueNode{
    public:
    	T data;
    	PriQueueNode<T>* link;
    	PriQueueNode(T& value):data(value),link(NULL){}
    };
    
    template <class T>
    class PriQueue{
    
    	PriQueueNode<T>* front;
    	PriQueueNode<T>* back;
    
    public:
    	PriQueue():front(NULL),back(NULL){}
    	void EnQueue(T& element);
    	T DelQueue();
    	T& GetFront();
    	void MakeEmpty();
    	bool IsEmpty();
    };
    
    template <class T>
    void PriQueue<T>::EnQueue(T& value)
    {
    	PriQueueNode<T>* add = new PriQueueNode<T>(value);
    	if(front == NULL)
    		front = back = add;
    	else
    	{
    		back->link = add;
    		back = back->link;
    	}
    }
    
    template <class T>
    T PriQueue<T>::DelQueue()
    {
    	PriQueueNode<T>* seek = front->link;		//遍历队列。寻找最小元素的指针
    	PriQueueNode<T>* min = front;       			//指向最小元素的指针
    	T minData;                        				//记录最小元素的数据
    	while(seek!=NULL){
    		if(seek->data < min->data)       		//寻找最小元素
    			min = seek;
    		seek = seek->link;
    	}
    
    	seek = front;                       			//指针重回队列头部
    	while(seek!=NULL&&seek->link!=min)			//寻找最小元素的前驱结点
    	{
    		seek = seek->link;
    	}
    
    	if(seek == NULL){							//假设最小元素位于队列头部
    		minData = front->data;
    		front = front->link;					//更新队头指针
    		delete min;
    	}
    
    	if(min->link == NULL)						//假设最小元素位于队列尾部
    		back = seek;							//更新队尾指针
    
    	if(seek!=NULL){								//假设最小元素位于队列中间,无需更新
    		minData = min->data;					//队头指针与队尾指针。直接删除就可以
    		seek->link = min->link;
    		delete min;
    	}
    	return  minData;							//返回数据
    } 
    
    template<class T>
    T& PriQueue<T>::GetFront(){
    	assert(!this->IsEmpty());
    		return front->data;
    }
    
    template<class T>
    void PriQueue<T>::MakeEmpty(){
    	while(!IsEmpty()){
    		this->DelQueue();
    	}
    }
    
    template<class T>
    bool PriQueue<T>::IsEmpty()
    {
    	return front == NULL;
    }
    

    P151:STL中的Stack应用演示样例1


    #include "stdafx.h"
    #include <iostream>
    #include <cstdlib>
    #include <stack>
    
    using namespace std;
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	stack<int> myStack;
    
    	//入栈与出栈
    	myStack.push(5);
    	myStack.push(6);
    	myStack.push(7);
    	myStack.pop();
    
    	cout << myStack.top() << endl;
    	cout << myStack.size() << endl;
    	cout << myStack.empty() << endl;
    
    
    	system("PAUSE");
    	return 0;
    }



    P152:STL中的Stack应用演示样例2


    #include "stdafx.h"
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <cstdlib>
    #include <stack>
    
    using namespace std;
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    
    	ifstream inf;
    	inf.open("temp.txt");
    
    	if ( !inf ) {
    		cerr << "cannot open file for input!" << endl;
    		return EXIT_FAILURE;
    	}
    
    	stack<string> s;
    	string line;
    
    	while (getline(inf, line)) {
    		s.push(line);
    	}
    
    	inf.close();
    
    	while (!s.empty()) {
    		cout << s.top() << endl;
    		s.pop();
    	}
    
    	system("PAUSE");
    	return 0;
    }

    P153: STL中的queue使用演示样例


    #include "stdafx.h"
    #include <iostream>
    #include <cstdlib>
    #include <queue>
    
    using namespace std;
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    
    	queue<int> myQueue;
    
    	//加入元素与删除元素
    	myQueue.push(5);
    	myQueue.push(6);
    	myQueue.push(7);
    
    	myQueue.pop();
    
    	cout << myQueue.front() << endl;
    	cout << myQueue.back() << endl;
    
    	cout << myQueue.size() << endl;
    	cout << myQueue.empty() << endl;
    
    	system("PAUSE");
    	return 0;
    }

    P154:基于FIFO策略的内存页面淘汰过程模拟


    #include "stdafx.h"
    #include <iostream>
    #include <cstdlib>
    #include <queue>
    
    using namespace std;
    
    bool existOrNot(int num, queue<int> myQueue)
    {
    	while(!myQueue.empty())
    	{
    		if(myQueue.front()==num)
    			return true;
    		else myQueue.pop();
    	}
    	return false;
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	queue<int> memQueue;
    
    	int page[] ={4, 3, 2, 1, 4, 3, 5, 4, 3, 2, 1, 5};
    	int times = 12;
    	int tmpValue;
    
    	for(int i = 0; i < 12; i++)
    	{
    		if(memQueue.size()<3)
    			memQueue.push(page[i]);
    		else 
    		{
    						
    			if(existOrNot(page[i], memQueue))
    			{
    				times--;
    			}
    			else
    			{
    				memQueue.pop();
    				memQueue.push(page[i]);
    			}
    		}
    
    		int size = memQueue.size();
    		while(size>0)
    		{
    			cout<<memQueue.front()<<" ";
    			tmpValue = memQueue.front();
    			memQueue.pop();
    			memQueue.push(tmpValue);
    			size--;
    		}
    
    		cout<<endl;
    	}
    	
    	cout<<"使用FIFO策略时。共发生缺页中断"<<times<<"次."<<endl;
    
    	system("PAUSE");
    	return 0;
    }
    
    

    P156:STL中的priority_queue使用演示样例1


    #include "stdafx.h"
    #include <iostream>
    #include <cstdlib>
    #include <queue>
    
    using namespace std;
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    
    	priority_queue<int> Q;
    	Q.push(1);
    	Q.push(5);
    	Q.push(2);
    	Q.push(4);
    	Q.push(6);
    	Q.push(3);
    	
    	int size = Q.size();
    
    	for(int i = 0; i< size; i++)
    	{
    		cout<<Q.top()<<endl;
    		Q.pop();
    	}
    
    	cout<< endl << Q.empty() <<endl;
    
    
    	system("PAUSE");
    	return 0;
    }


    P157:STL中的priority_queue使用演示样例2


    #include "stdafx.h"
    #include <iostream>
    #include <cstdlib>
    #include <queue>
    
    using namespace std;
    
    class myCompare{
    public:
        bool operator () (const int& a,const int& b)
        {
            return a > b;
        }
    };
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	priority_queue<int, vector<int>, myCompare> Q;
    	Q.push(1);
    	Q.push(5);
    	Q.push(2);
    	Q.push(4);
    	Q.push(6);
    	Q.push(3);
    	
    	int size = Q.size();
    
    	for(int i = 0; i < size; i++)
    	{
    		cout<<Q.top()<<endl;
    		Q.pop();
    	}
    
    	cout<< endl << Q.empty() <<endl;
    
    	system("PAUSE");
    	return 0;
    }


    P161:阶乘的递归求解函数


    int factorial(int n) {
    	if (n == 0) {
    		return 1;
    	} 
    	else {
    		int value = factorial(n - 1);
    		return n * value;
    	}
    }
    


    P163:递归实现的二分查找


    #include "stdio.h"
    #include <vector>
    #include <iostream>
    
    using namespace std;
    
    int binarySearch(const vector<int> & a, const int & x, int low, int high)
    {
    	if(low>high)
    		return -1;
    
    	int mid = (low + high)/2;
    	//二分查找法的递归核心部分
    	if(a[mid]<x)
    		return binarySearch(a, x, mid+1, high);
    	else if(x<a[mid])
    		return binarySearch(a, x, low, mid-1);
    	else
    		return mid;
    }
    
    int Search(const vector<int> & a, const int & x)
    {
    	return binarySearch(a, x, 0, a.size()-1);
    }
    
    void main()
    {
    	vector<int> box;
    
    	box.push_back(1);
    	box.push_back(4);
    	box.push_back(6);
    	box.push_back(7);
    	box.push_back(8);
    	box.push_back(10);
    	box.push_back(13);
    	box.push_back(21);
    	box.push_back(22);
    	box.push_back(30);
    
    	const int searchValue = 22;
    
    	int result = Search(box, searchValue);
    
    	if(result == -1)
    		cout<<"要查的数字不在数组内。"<<endl;
    	else
    		cout<<searchValue<<"的位置在第"<<++result<<"位"<<endl;
    }
    


    P164:斐波那契数列的递归实现


    int Fib(int n){
    	if(n<=1) return n;
    	else return Fib(n-1)+Fib(n-2);
    }
    


    P165:递归的顺序演示样例程序


    #include "stdio.h"
    
    void recursiveFunction1 ( int num ) 
    { 
    	if ( num < 5 ) 
    	{ 
    		printf ( "%d 
    " , num ) ; 
    		recursiveFunction1 ( num +1 ) ; 
    	} 
    }
    
    void recursiveFunction2 ( int num ) 
    { 
    	if ( num < 5 ) 
    	{ 
    		recursiveFunction2 ( num +1 ) ; 
    		printf ( "%d 
    " , num ) ; 
    	}
    }
    
    void main()
    {
    	recursiveFunction1(0);
    	recursiveFunction2(0);
    }
    

    P168-1:求和函数的递归实现


    int Sum( int n )
    {
    	if ( n==1 )
    		return 1;
    	else
    		return Sum(n-1)+n;
    }
    


    P168-2:斐波那契数列的迭代实现


    int Fib ( int n ) { 
    	if ( n <= 1 ) return n; 
    	int twoback = 0;
    	int oneback = 1;
    	int Current;
    	for ( int i = 2; i <= n; i++ ) { 
    		Current = twoback + oneback;
    		twoback = oneback;
    		oneback = Current; 
    	 } 
    	return Current; 
    } 
    

    P169:阶乘函数的尾递归实现


    int factorial(int acc , int x) 
    {
    	if (x <= 1)
    		return acc;
    	else 
    		return factorial ( x * acc, x - 1 );
    }
    


    P170-1:求解最大公约数的欧几里德算法(尾递归实现)


    int gcd(int a, int b)
    {
    	if (b == 0)
    		return a;
    	else
    		return gcd(b, a%b);
    }
    


    P170-2:求解最大公约数的欧几里德算法(非递归实现)


    int gcd ( int a, int b ) 
    { 
    	while ( b != 0 )
    	{ 
    		int r = a % b; 
    		a = b; 
    		b = r; 
    	} return a;
    }
    


    P173: 汉诺塔问题


    #include "stdafx.h"
    #include <fstream>
    #include <iostream>
    
    using namespace std;
    
    //盘子的数目
    #define numOfDisks 10
    
    //在文本文件out.txt中输出结果
    ofstream fout("out.txt");
    
    void Move(int n,char x,char y)
    {
    	fout<<"move "<<n<<" from "<<x<<" to "<<y<<endl;
    }
    
    //递归求解
    void Hannoi(int n,char a,char b,char c)
    {
    	if(n==1)
    		Move(1,a,c);
    	else
    	{
    		Hannoi(n-1,a,c,b);
    		Move(n,a,c);
    		Hannoi(n-1,b,a,c);
    	}
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	fout<<"The solution for Hanoi, when the number of disks is "<<
    		numOfDisks<<endl;
    	Hannoi(numOfDisks,'a','b','c');
    	fout.close();
    	cout<<"The End! Please Check out.txt."<<endl;
    
    	system("pause"); 
    	return 0;
    }

    P175:传染病问题


    main.cpp文件


    #include <iostream>
    #include <string>
    #include <cstdlib>
    
    #include "grid.h"
    
    using namespace std;
    
    #define ROWS 6
    #define COLS 6
    #define TOTAL 13 // 被感染点的总数
    
    // 标记被感染点的坐标的数组
    int theCity[TOTAL][2] = {
    	{0,0},
    	{1,1},
    	{2,2},
    	{2,3},
    	{2,5},
    	{3,2},
    	{3,3},
    	{3,5},
    	{4,0},
    	{4,2},
    	{4,3},
    	{4,5},
    	{5,0}
    };
    
    int main () {
    
      grid *g;
      int col;
      int row;
    
      g = new grid ((int*)theCity, ROWS, COLS, TOTAL);
    
      cout << "请输入要检測点的坐标 格式: x,y" << endl;
      scanf("%d,%d", &row, &col);
    
      cout << "The colony including the cell at " 
           << "(" << row << "," << col << ")"
           << " has an area of " << g->count (row,col) << " units." << endl;
    
      cout << *g << endl;
    
      delete g;
      
      return EXIT_SUCCESS;
    }
    

    grid.h文件


    #ifndef GRID_H
    #define GRID_H
    
    #include <string>
    #include <vector>
    
    using namespace std;
    
    const bool INFECTED = true;
    const bool NOT_INFECTED = false;
    
    class grid;
    
    class grid {
    
        int rows;
        int cols;
    	int number;
        vector<bool> *area;
    	vector<bool> *marked_area;
    
        int indexof (int row, int col) const;
        bool infected(int row, int col) const;
    	void caculate(int row,int col);
    
      public:
        grid (int* theCity, int, int, int);
        ~grid ();
    
        int count (int row, int col);
    
        friend ostream &operator<<(ostream &stream, const grid& ob);
    
    };
    
    #endif
    

    grid.cpp文件


    #include <iostream>
    #include <fstream>
    
    using namespace std;
    
    #include "grid.h"
    
    int grid::indexof (int row, int col) const {
      return row*cols+col;
    }
    
    bool grid::infected(int row, int col) const {
      return (area->operator[](indexof(row, col)) == INFECTED);
    }
    
    //构造函数
    grid::grid (int* theCity, int row, int col, int total) {
    
      number=0;
    
      rows = row;
      cols = col;
    
      area = new vector<bool>(rows*cols, NOT_INFECTED);
      marked_area = new vector<bool>(rows*cols, NOT_INFECTED);
    
      for (int i=0; i<total; i++) { 
      
        int blob_row;
        int blob_col;
    
    	blob_row = theCity[i*2];
    	blob_col = theCity[i*2+1];
    
        area->operator[](indexof(blob_row,blob_col)) = INFECTED;
      }
    }
    
    //析构函数
    grid::~grid () {
      delete area;
      delete marked_area;
    }
    
    //在被感染的细胞处加入一个(+),运算符重载
    ostream &operator<<(ostream &stream, const grid& ob) {
    
      for (int row=0; row < ob.rows; row++) { 
        
        for (int col=0; col < ob.cols; col++) {
          stream << ob.area->operator[](ob.indexof(row, col));
    	  if(ob.marked_area->operator[](ob.indexof(row, col)))
    		  stream << "+  ";
    	  else
    		  stream << "   ";
        }
    
        stream << endl;
      }
    
      stream << endl;
      return stream;
    }
    
    int grid::count (int row, int col) 
    {
    	caculate(row,col);
        return number;
    }
    
    //递归核心部分,进行八个方向的检查
    void grid::caculate(int row,int col)
    {
    	if (row<0||col<0||row>=rows||col>=cols||marked_area->operator [](indexof(row,col)))
    		return;
    	if (infected(row,col))
    	{
    		marked_area->operator[](indexof(row, col)) = INFECTED;
    		number++;
    		caculate(row,col+1);
    		caculate(row,col-1);
    		caculate(row+1,col);
    		caculate(row-1,col);
    		caculate(row+1,col+1);
    		caculate(row-1,col-1);
    		caculate(row+1,col-1);
    		caculate(row-1,col+1);
    	}
    }
    

    sample.grid 文件内容


    6 6
    
    0 0
    1 1
    2 2
    2 3
    2 5
    3 2
    3 3
    3 5
    4 0
    4 2
    4 3
    4 5
    5 0


    P177:迷宫问题


    #include <vector>
    #include <iostream>
    using namespace std;
    
    // 把迷宫表示为n个有编码路口的集合
    // 定义路口类
    class Crossing
    {
    public:
    	// 0为不通 路口的三个方向
    	int turn1;
    	int turn2;
    	int turn3;
    
    public:
    	Crossing(int turn1, int turn2, int turn3)
    	{
    		Crossing::turn1 = turn1;
    		Crossing::turn2 = turn2;
    		Crossing::turn3 = turn3;
    	}	
    };
    
    // 定义迷宫类
    class Maze
    {
    private:
    	int exit; //出口编码
    	vector<Crossing> crossings; //路口集合
    	vector<int> result;
    
    public:
    	Maze(int the_exit, vector<Crossing> the_crossings)
    	{
    		exit = the_exit;
    		crossings = the_crossings;
    	}
    	findExit(int entrance); //迷宫求解
    	getResult(); //取得迷宫解并打印
    	
    };
    
    //迷宫求解核心算法
    Maze::findExit(int entrance)
    {
    	if(entrance > 0)
    	{
    		if(entrance == Maze::exit)
    		{
    			result.push_back(entrance);
    			return 1;
    		}
    		if(findExit(crossings[entrance].turn1))
    		{
    			result.push_back(entrance);
    			return 1;
    		}
    		if(findExit(crossings[entrance].turn2))
    		{
    			result.push_back(entrance);
    			return 1;
    		}
    		if(findExit(crossings[entrance].turn3))
    		{
    			result.push_back(entrance);
    			return 1;
    		}
    	}
    
    	return 0;
    }
    
    Maze::getResult()
    {
    	findExit(1);
    	
    	for(int i = result.size(); i>0; i--)
    		cout << result[i-1] << "->";
    	cout << "Exit" << endl;
    }
    
    void main()
    {
    	// 创建一个迷宫 9个路口 出口为10
    	Crossing c1(2,0,0);
    	Crossing c2(4,0,0);
    	Crossing c3(0,0,0);
    	Crossing c4(3,5,0);
    	Crossing c5(6,0,0);
    	Crossing c6(7,0,0);
    	Crossing c7(8,9,0);
    	Crossing c8(0,0,0);
    	Crossing c9(10,0,0);
    	Crossing c0(0,0,0);
    
    	vector<Crossing> crossings;
    	crossings.push_back(c0);
    	crossings.push_back(c1);
    	crossings.push_back(c2);
    	crossings.push_back(c3);
    	crossings.push_back(c4);
    	crossings.push_back(c5);
    	crossings.push_back(c6);
    	crossings.push_back(c7);
    	crossings.push_back(c8);
    	crossings.push_back(c9);
    
    	Maze newMaze(10, crossings);
    	newMaze.getResult();
    
    	return;
    }
    


    P182:八皇后问题


    #include <conio.h>
    #include <iostream>
    
    using namespace std;
    // 首先 要求皇后不冲突,那么每行仅仅应该有一个皇后
    // 用queens[]数组在存储每一个皇后的位置
    // 比如: queens[m] = n 表示 第m行的皇后放在第n列上
    
    #define MAX 8
    
    int sum = 0;
    class QueenPuzzle
    {
        int queens[MAX]; // 存储每行皇后的列标
     
    public:
        void printOut(); // 打印结果
        int IsValid(int n); //推断第n个皇后放上去之后。是否合法
        void placeQueen(int i); // 递归算法 放置皇后
    };
    
    void QueenPuzzle::printOut()
    {
        for(int i=0; i<MAX; i++)
        {
            for(int j=0; j<MAX; j++)
            {
                if(j == queens[i])
                    cout << "Q ";
                else
                    cout << "0 ";
            }
            cout << endl;
        }
    
        cout << endl << "按q键盘退出,按其它键继续" << endl << endl;
    
        if(getch() == 'q')
            exit(0);
    }
    
    // 在第i行放置皇后
    void QueenPuzzle::placeQueen(int i)
    {
        for(int j=0; j<MAX; j++)
        {
            // 假设所有放完了 输出结果
            if(i == MAX)
            {
                sum ++;
                cout << "第" << sum << "组解:" << endl;
                printOut();
       
                return;
            }
    
        // 放置皇后
        queens[i] = j;
        // 此位置不能放皇后 继续试验下一位置
        if(IsValid(i))
            placeQueen(i+1);
        }
    }
    
    //推断第n个皇后放上去之后。是否合法,即是否无冲突 
    int QueenPuzzle::IsValid(int n) 
    { 
        //将第n个皇后的位置依次于前面n-1个皇后的位置比較。 
        for(int i = 0 ; i < n ; i++) 
        { 
            //两个皇后在同一列上,返回0 
            if(queens[i] == queens[n]) 
                return 0;
     
            //两个皇后在同一对角线上,返回0 
            if(abs(queens[i] - queens[n]) == (n - i)) 
                return 0; 
        }
    
        //没有冲突。返回1。

    return 1; } void main() { QueenPuzzle queen; queen.placeQueen(0); cout << "共" << sum << "组解" << endl; }


    内容简单介绍:探秘算法世界,求索数据结构之道。汇集经典问题。畅享编程技法之趣;点拨求职热点,敲开业界名企之门。

    本书环绕算法与数据结构这个话题,循序渐进、深入浅出地介绍了现代计算机技术中经常使用的四十余个经典算法,以及回溯法、分治法、贪婪法和动态规划等算法设计思想。

    在此过程中,本书也系统地解说了链表(包含单向链表、单向循环链表和双向循环链表)、栈、队列(包含普通队列和优先级队列)、树(包含二叉树、哈夫曼树、堆、红黑树、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


  • 相关阅读:
    [置顶] Objective-C,/,ios,/iphone开发基础:分类(category,又称类别)
    23个移动app界面上的旋钮和刻度盘设计示例
    com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: SELECT command denied to user’
    山沟沟里的实业路(3)
    挨踢江湖之十九
    如何用Python从本地将一个文件备份到Google Drive
    SQL Server 索引和表体系结构(包含列索引)
    UVa 263
    C语言之基本算法40—字符串删除元音字母倒序输出
    【Spark亚太研究院系列丛书】Spark实战高手之路-第一章 构建Spark集群(第五步)(1)
  • 原文地址:https://www.cnblogs.com/zsychanpin/p/7095656.html
Copyright © 2011-2022 走看看