标签:
本文辑录了《算法之美——隐匿在数据结构背后的语言》(电子工业出版社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 \n" , num ) ; recursiveFunction1 ( num +1 ) ; } } void recursiveFunction2 ( int num ) { if ( num < 5 ) { recursiveFunction2 ( num +1 ) ; printf ( "%d \n" , 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); } }
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:八皇后问题
请参见博文
内容简介:探秘算法世界,求索数据结构之道;汇集经典问题,畅享编程技法之趣;点拨求职热点,敲开业界名企之门。本书围绕算法与数据结构这个话题,循序渐进、深入浅出地介绍了现代计算机技术中常用的四十余个经典算法,以及回溯法、分治法、贪婪法和动态规划等算法设计思想。在此过程中,本书也系统地讲解了链表(包括单向链表、单向循环链表和双向循环链表)、栈、队列(包括普通队列和优先级队列)、树(包括二叉树、哈夫曼树、堆、红黑树、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
标签:
原文地址:http://blog.csdn.net/baimafujinji/article/details/50602547