本文辑录了《算法之美——隐匿在数据结构背后的语言》(电子工业出版社2016年出版)一书第4~5章之代码(P118~P148)。全文目录、“45个算法”目录、“22个经典问题目录”,以及有奖捉虫活动详情请见如下链接:http://blog.csdn.net/baimafujinji/article/details/50484348
附录中的经典笔试、面试问题参考答案请见:
http://blog.csdn.net/baimafujinji/article/details/50484683
内容简介:探秘算法世界,求索数据结构之道;汇集经典问题,畅享编程技法之趣;点拨求职热点,敲开业界名企之门。本书围绕算法与数据结构这个话题,循序渐进、深入浅出地介绍了现代计算机技术中常用的四十余个经典算法,以及回溯法、分治法、贪婪法和动态规划等算法设计思想。在此过程中,本书也系统地讲解了链表(包括单向链表、单向循环链表和双向循环链表)、栈、队列(包括普通队列和优先级队列)、树(包括二叉树、哈夫曼树、堆、红黑树、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
P118:游标类的定义
template <class T> class Iterator{
ListNode<T>* cur;
public:
Iterator():cur(NULL){};
Iterator(ListNode<T>* point):cur(point){}
friend T operator ++(Iterator& it); //前缀
friend T operator ++ (Iterator& it,int); //后缀
friend bool operator == (Iterator& it,ListNode<T>* point);
friend bool operator != (Iterator& it,ListNode<T>* point);
friend ostream& operator<< (ostream& stream,Iterator& it);
void operator= (ListNode<T>* point);
ListNode<T>*& GetCur();
};
//前缀运算符,先返回cur所指结点中的数据
//再使cur向后移动
template <class T>
T operator++(Iterator<T>& it){
it.GetCur() = it.GetCur()->GetLink();
T data;
data = it.GetCur()->GetData();
return data;
}
//后缀运算符,先使cur向后移动一个结点
//再返回cur所指结点中的数据
template <class T>
T operator++(Iterator<T>& it,int){
T data;
data = it.GetCur()->GetData();
it.GetCur() = it.GetCur()->GetLink();
return data;
}
//判断cur是否等于point
template <class T>
bool operator==(Iterator<T>& it,ListNode<T>* point){
return it.GetCur() == point;
}
//判断cur是否不等于point
template <class T>
bool operator!=(Iterator<T>& it,ListNode<T>* point){
return it.GetCur() != point;
}
//输出cur所指结点中的数据
template <class T>
ostream& operator<<(ostream& stream,Iterator<T>& it){
stream<<it.GetCur()->GetData();
return stream;
}
//把point的值赋给cur
template <class T>
void Iterator<T>::operator = (ListNode<T>* point){
cur = point;
}
//返回cur
template <class T>
ListNode<T>*& Iterator<T>::GetCur(){
return cur;
}
template <class T> class Iterator{
DouListNode<T>* cur;
public:
Iterator():cur(NULL){};
Iterator(DouListNode<T>* point):cur(point){}
friend T operator++(Iterator& it); //前缀
friend T operator++(Iterator& it,int); //后缀
friend T operator--(Iterator& it); //前缀
friend T operator--(Iterator& it,int); //后缀
friend bool operator==(Iterator& it,DouListNode<T>* point);
friend bool operator!=(Iterator& it,DouListNode<T>* point);
friend ostream& operator<< (ostream& stream,Iterator& it);
void operator= (DouListNode<T>* point);
DouListNode<T>*& GetCur();
};
P121:双向链表游标类的实现
template <class T>
T operator++(Iterator<T>& it){
it.GetCur() = it.GetCur()->GetLink();
T data;
data = it.GetCur()->GetData();
return data;
}
template <class T>
T operator++(Iterator<T>& it,int){
T data;
data = it.GetCur()->GetData();
it.GetCur() = it.GetCur()->GetLink();
return data;
}
template <class T>
T operator--(Iterator<T>& it){
it.GetCur() = it.GetCur()->GetPrior();
T data;
data = it.GetCur()->GetData();
return data;
}
template <class T>
T operator--(Iterator<T>& it,int){
T data;
data = it.GetCur()->GetData();
it.GetCur() = it.GetCur()->GetPrior();
return data;
}
template <class T>
bool operator==(Iterator<T>& it,DouListNode<T>* point){
return it.GetCur() == point;
}
template <class T>
bool operator!=(Iterator<T>& it,DouListNode<T>* point){
return it.GetCur() != point;
}
template <class T>
ostream& operator<<(ostream& stream,Iterator<T>& it){
stream<<it.GetCur()->GetData();
return stream;
}
template <class T>
void Iterator<T>::operator = (DouListNode<T>* point){
cur = point;
}
template <class T>
DouListNode<T>*& Iterator<T>::GetCur(){
return cur;
}
P122:STL中的list使用示例
#include "stdafx.h"
#include <iostream>
#include <string>
#include <cstdlib>
#include <list>
using namespace std;
int _tmain(int argc, _TCHAR* argv[]) {
list<int> myList1;
myList1.push_front(10);
cout << myList1.size() << endl; //链表长度为 1
list<string> myList2 (10);
cout << myList2.size() << endl; //链表长度为 10
list<double> myList3 (2, 4.6); //初始值为4.6
cout << myList3.back() << endl;
myList3.pop_back();
cout << myList3.empty() << endl;
system("PAUSE");
return 0;
}
P122:STL中的list使用示例2
#include "stdafx.h"
#include <iostream>
#include <string>
#include <cstdlib>
#include <list>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
string str[] = {"Today ","is ","not ","Friday."};
list<string> eraseThird;
for(int i = 0; i < 4; i++)
eraseThird.push_back(str[i]);
// 删除链表中的第3个元素
list<string>::iterator third = eraseThird.begin();
++third;
++third;
eraseThird.erase(third);
list<string>::iterator third2 = eraseThird.begin();
third2 ++;
third2 ++;
eraseThird.insert(third2, "not ");
list<string>::iterator it = eraseThird.begin() ;
while (it != eraseThird.end()) {
cout << *it ;
++it;
}
cout<<endl;
list<int> list1(15, 3);
list<int> list2(16, 2);
list<int>::iterator insertMass = list1.begin();
insertMass++;
list1.insert(insertMass, list2.begin(), list2.end());
cout << list1.size() << endl;
system("PAUSE");
return 0;
}P129:顺序栈的实现
template <class T>
class ArrayStack{
int size;
int tos; //栈顶索引。
T* contain;
public:
ArrayStack():size(0),tos(-1),contain(NULL){}
ArrayStack(int MaxSize);
void Push(T& element);
T& GetTop();
T& Pop();
bool IsEmpty();
void MakeEmpty();
};
template<class T>
ArrayStack<T>::ArrayStack(int MaxSize)
{//构造函数
size= MaxSize;
tos =-1; //初始化tos于栈底处。
contain= new T[size];
}
template<class T>
void ArrayStack<T>::Push(T& element)
{//向栈中添加新元素
assert(tos!= size-1);
contain[++tos]= element;
}
template<class T>
T& ArrayStack<T>::Pop()
{//从栈中删除元素
assert(tos!=-1);
returncontain[tos--];
}
template<class T>
T& ArrayStack<T>::GetTop()
{//返回栈顶元素
assert(tos!=-1);
returncontain[tos];
}
template<class T>
void ArrayStack<T>::MakeEmpty()
{//置空栈
tos =-1;
}
template<class T>
bool ArrayStack<T>::IsEmpty()
{//判断栈是否为空。
returntos==-1;
}P131:链式栈的实现
#ifndef LINKSTACK_H
#define LINKSTACK_H
#include <iostream>
#include <assert.h>
using namespace std;
template <class T>
class LinkStackNode{
public :
T data;
LinkStackNode<T>* link;
LinkStackNode(T& value):link(NULL),data(value){}
};
template <class T>
class LinkStack{
LinkStackNode<T>* tos;
public :
LinkStack():tos(NULL){}
void Push(T& value);
T& GetTop();
T Pop();
bool IsEmpty();
void MakeEmpty();
};
template<class T>
void LinkStack<T>::Push(T& value){
LinkStackNode<T>* add = new LinkStackNode<T>(value);
add->link = tos;
tos = add;
}
template<class T>
T& LinkStack<T>::GetTop(){
return tos->data;
}
template<class T>
T LinkStack<T>::Pop(){
assert(tos!=NULL);
LinkStackNode<T>* old = tos;
tos = tos->link;
T data = old->data;
delete old;
return data;
}
template<class T>
bool LinkStack<T>::IsEmpty()
{
return tos == NULL;
}
template<class T>
void LinkStack<T>::MakeEmpty()
{
while(!this->IsEmpty()){
this->Pop();
}
}
#endifP132:括号匹配问题
请参见博文——括号匹配问题与经典笔试面试题目解析
(链接地址:http://blog.csdn.net/baimafujinji/article/details/50465482)
P134:停车场模拟问题
car.h文件
#ifndef CAR_H
#define CAR_H
#include <iostream>
#include <string>
using namespace std;
//Declaration of class car.
//Instances of class car need to store the license plate
//and the number of times the car has been moved while it has been parked in the lot.
class car {
private:
string license;
int movedTimes;
public:
car(string,int);
string getLicense()const;
int getMovedTimes()const;
void move();
virtual ~car();
};
#endif#include "car.h"
using namespace std;
//构造函数
car::car(string license,int):movedTimes(0),license(license){}
//析构函数
car::~car(){}
//返回车辆被移动的次数
int car::getMovedTimes()const
{
return movedTimes;
}
//返回车辆的代号
string car::getLicense()const
{
return license;
}
//当车被移动时,属性movedTimes 自加1
void car::move()
{
movedTimes++;
}
main.cpp文件
#include <string>
#include <STACK>
#include <iostream>
#include <fstream>
#include "car.h"
using namespace std;
#define EXIT_FAILURE 0
#define EXIT_SUCCESS 1
int main(int argc, char *argv[])
{
//The user should specify the data file to use via the command-line.
if (argc != 2) {
cerr << "Usage: " << argv[0] << " data-file\n";
cerr << "You shoud use this program in the cmd line"<<endl;
return EXIT_FAILURE;
}
//Judge whether the file exists or not
//Then open the file for reading or writing
string in_fileName = argv[1];
string out_fileName = "result.txt";
ifstream infs(in_fileName.c_str());
ofstream outfs(out_fileName.c_str());
if(!infs){
cerr<<"Can‘t open the file "<<in_fileName<<endl;
return EXIT_FAILURE;
}
if(!outfs){
cerr<<"Can‘t open the file "<<out_fileName<<endl;
return EXIT_FAILURE;
}
//Declare a stack object to represent the single-aisle parking lot.
//This object must be of type stack<car*>
//To preserve the order of the other cars, a temporary stack of type pointer to car should be used.
stack<car*> parking_lot, tempStack;
car *pcar;
string license_plate,action;
//Unless the file ends, then read it.
while(!infs.eof())
{
infs>>license_plate>>action;
//For each arrival, instantiate an object of type car in the free store
if(action=="arrives")
{
if(parking_lot.size()<5)
{
pcar=new car(license_plate,0);
parking_lot.push(pcar);
}
//Output a meaningful message if the parking lot is full.
//The lot is full when the stack contains five elements.
else
outfs<<"Sorry "<<license_plate<<" , The lot is full ! "<<endl;
}
//For each departure, remove the corresponding car pointer from the stack
else if(action=="departs")
{
while(!parking_lot.empty()&&parking_lot.top()->getLicense() != license_plate)
{
tempStack.push(parking_lot.top());
parking_lot.top()->move();
parking_lot.pop();
}
//Output the number of times this car was moved while it was parked in the lot
if(parking_lot.top()->getLicense() == license_plate)
{
outfs<<parking_lot.top()->getLicense()<<" was moved "<<parking_lot.top()->getMovedTimes()<<" times while it was here"<<endl;
delete parking_lot.top();
parking_lot.pop();
}
else
outfs<<"Exception!"<<endl;
while(!tempStack.empty())
{
parking_lot.push(tempStack.top());
tempStack.pop();
}
}
}
//Output the number of times each car that remains in the lot (if there are any) was moved.
outfs<<"\n\nThese cars are still in the lot \n\n";
while(!parking_lot.empty())
{
outfs<<parking_lot.top()->getLicense()<<" was moved "<<parking_lot.top()->getMovedTimes()<<" times while it was here"<<endl;
delete parking_lot.top();
parking_lot.pop();
}
outfs.close();
infs.close();
cout<<"The result.txt is created ,you can check it now!"<<endl;
return EXIT_SUCCESS;
}用于测试的data.txt文件,测试结果请参见P134之图5-4
A arrives A departs B arrives C arrives D arrives C departs E arrives F arrives G arrives B departs H arrives D departs E departs I arrives I departs J arrives F departs K arrives L arrives M arrives H departs N arrives J departs K departs O arrives P arrives P departs O departs L departs
P138:循环队列的实现
template <class T>
class CirQueue{
int size;
int front;
int back;
T* contain;
public:
CirQueue():size(0),front(0),back(0),contain(NULL){}
CirQueue(int MaxSize);
void EnQueue(T& element);
T DelQueue();
T& GetFront();
void MakeEmpty();
bool IsEmpty();
bool IsFull();
};
template <class T>
CirQueue<T>::CirQueue(int MaxSize):size(MaxSize+1),front(0),back(0)
{//构造函数
contain = new T[MaxSize+1];
}
template <class T>
void CirQueue<T>::EnQueue(T& element)
{//向队列中添加新元素
assert(!IsFull());
contain[back] = element;
back = (back+1)%size;
}
template <class T>
T CirQueue<T>::DelQueue()
{//从队列中删除元素
int old = front;
front = (front+1)%size;
return contain[old];
}
template <class T>
T& CirQueue<T>::GetFront()
{//返回队头元素
assert(!IsEmpty());
return contain[front];
}
template <class T>
void CirQueue<T>::MakeEmpty()
{//置空队列
front = back = 0;
}
template <class T>
bool CirQueue<T>::IsEmpty()
{//判断队列是否为空
return front == back;
}
template <class T>
bool CirQueue<T>::IsFull()
{//判断队列是否已满
return (back+1)%size == front;
}
P140:链式队列的实现
#ifndef LINKQUEUE_H
#define LINKQUEUE_H
#include <iostream>
#include <assert.h>
using namespace std;
template <class T>
class LinkQueue{
struct LinkQueueNode
{
T data;
LinkQueueNode *link;
LinkQueueNode(T & theData, LinkQueueNode * n = NULL ): data( theData ), link( n ) { }
};
LinkQueueNode* front;
LinkQueueNode* back;
public:
LinkQueue();
~LinkQueue();
void EnQueue(T& element);
T DelQueue();
T& GetFront();
void MakeEmpty();
bool IsEmpty();
};
template <class T>
LinkQueue<T>::LinkQueue()
{
front = back = NULL;
}
template <class T>
LinkQueue<T>::~LinkQueue()
{
this->MakeEmpty();
}
template <class T>
void LinkQueue<T>::EnQueue(T& value)
{
if(this->IsEmpty())
front = back = new LinkQueueNode(value);
else
back = back->link = new LinkQueueNode(value);
}
template <class T>
T LinkQueue<T>::DelQueue()
{
LinkQueueNode* old = front;
T data = old->data;
front = front->link;
delete old;
return data;
}
template <class T>
T& LinkQueue<T>::GetFront()
{
assert(!IsEmpty());
return front->data;
}
template <class T>
void LinkQueue<T>::MakeEmpty()
{
while(!this->IsEmpty()){
this->DelQueue();
}
}
template <class T>
bool LinkQueue<T>::IsEmpty()
{
return front == NULL;
}
#endifP142:舞伴问题
#include "stdafx.h"
#include "LinkQueue.h"
#include <string>
#include <iostream>
using namespace std;
struct dancer{
string name;
char sex;
};
int _tmain(int argc, _TCHAR* argv[])
{
cout<<"请输入舞者总数:";
int num;
cin>>num;
LinkQueue<dancer> Mdancer;
LinkQueue<dancer> Fdancer;
for(int i=0;i<num;i++){
cout<<"请输入舞者性别(f or m)及姓名:";
char sex;
cin>>sex;
string name;
cin>>name;
dancer newdancer;
newdancer.name = name;
newdancer.sex = sex;
if(sex == ‘f‘)
Fdancer.EnQueue(newdancer);
if(sex == ‘m‘)
Mdancer.EnQueue(newdancer);
}
while(!Mdancer.IsEmpty() && !Fdancer.IsEmpty()){
cout<<Mdancer.DelQueue().name<<"\t<---->\t"<<Fdancer.DelQueue().name<<endl;
}
if(!Mdancer.IsEmpty()){
cout<<"Mr. "<<Mdancer.GetFront().name<<" is waiting!"<<endl;
}
else if(!Fdancer.IsEmpty()){
cout<<"Ms. "<<Fdancer.GetFront().name<<" is waiting!"<<endl;
}
else
cout<<"OK!"<<endl;
system("PAUSE");
return 0;
}请参见博文——杨辉三角与一道经典笔试面试题目
(链接地址:http://blog.csdn.net/baimafujinji/article/details/50436170)
P145:游程编码问题
#include "stdafx.h"
#include <queue>
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
queue<int> picture;
char a;
float pow = 0;
float oriSize;
cout<<"请输入01序列(以#结束):";
do{
cin>>a;
if(a!=‘#‘)
picture.push(a);
}while(a != ‘#‘);
char pic = picture.front();
picture.pop();
int size = picture.size()+1;
oriSize = size;
cout<<"编码后:";
while(!picture.empty()){
if(pic == picture.front()){
pic = picture.front();
picture.pop();
}
else{
cout<<size - picture.size();
pow++;
size = picture.size();
pic = picture.front();
picture.pop();
}
}
cout<<size<<endl;
pow++;
cout<<"压缩率为:"<<pow/oriSize<<endl;
system("PAUSE");
return 0;
}
原文:http://blog.csdn.net/baimafujinji/article/details/50485591