Algorithm for graph post dominance? - c++

What algorithm can be used to calculate post dominators in a control flow graph?
Currently I calculate the dominators by using the iterative bit vector algorithm:
#include <iostream>
#include <list>
#include <stack>
#include <vector>
#include <memory>
#include <map>
class BasicBlock
{
public:
BasicBlock(std::string name) : mName(name) { }
void AllocateDominatorsAndSetToTrue(const size_t nBlocks)
{
mDominators.resize(nBlocks);
for (size_t i = 0; i < nBlocks; i++)
{
mDominators[i] = true;
}
}
void SetAllDominatorsTo(bool value)
{
for (size_t i = 0; i < mDominators.size(); i++)
{
mDominators[i] = value;
}
}
std::string mName;
int mId = 0;
// Links to blocks before this one
std::vector<BasicBlock*> mPredecessors;
// Links to blocks after this one
std::vector<BasicBlock*> mSucessors;
std::vector<bool> mDominators;
std::vector<BasicBlock*> mImmediateDominator;
};
class ControlFlowGraph
{
public:
void AddBasicBlock(std::string name)
{
mBasicBlocks.emplace_back(std::make_unique<BasicBlock>(name));
}
void AddSucessor(std::string block, std::string target)
{
FindBlock(block)->mSucessors.emplace_back(FindBlock(target));
}
void AddPredecessor(std::string block, std::string target)
{
FindBlock(block)->mPredecessors.emplace_back(FindBlock(target));
}
BasicBlock* FindBlock(std::string name)
{
for (const auto& block : mBasicBlocks)
{
if (block->mName == name)
{
return block.get();
}
}
return nullptr;
}
void CalculateDominators()
{
const size_t nBlocks = mBasicBlocks.size();
int i = 0;
for (std::unique_ptr<BasicBlock>& block : mBasicBlocks)
{
block->mId = i++;
block->AllocateDominatorsAndSetToTrue(nBlocks);
}
BasicBlock* block = mBasicBlocks[0].get();
block->SetAllDominatorsTo(false);
block->mDominators[block->mId] = true; // block always dominates itself
bool changed = false;
do
{
changed = false;
for (std::unique_ptr<BasicBlock>& b : mBasicBlocks)
{
if (b == mBasicBlocks[0]) // Is it the entry node?
{
continue;
}
for (BasicBlock* pred : b->mPredecessors)
{
auto T = b->mDominators;
for (size_t i = 0; i < nBlocks; i++)
{
if (b->mDominators[i] && pred->mDominators[i])
{
b->mDominators[i] = true;
}
else
{
b->mDominators[i] = false;
}
}
b->mDominators[b->mId] = true; // block always dominates itself
if (b->mDominators != T)
{
changed = true;
}
}
}
}
while (changed);
}
void CalculateImmediateDominators()
{
// ??
}
std::vector<std::unique_ptr<BasicBlock>> mBasicBlocks;
};
int main()
{
ControlFlowGraph graph;
graph.AddBasicBlock("1");
graph.AddBasicBlock("2");
graph.AddBasicBlock("3");
graph.AddBasicBlock("4");
graph.AddBasicBlock("5");
graph.AddBasicBlock("6");
graph.AddSucessor("1", "2");
graph.AddSucessor("2", "3");
graph.AddSucessor("2", "4");
graph.AddSucessor("3", "2");
graph.AddSucessor("4", "5");
graph.AddSucessor("4", "6");
graph.AddSucessor("5", "4");
graph.AddSucessor("6", "2");
graph.AddPredecessor("2", "1");
graph.AddPredecessor("3", "2");
graph.AddPredecessor("4", "2");
graph.AddPredecessor("5", "4");
graph.AddPredecessor("6", "4");
graph.CalculateDominators();
graph.CalculateImmediateDominators();
return 0;
}

Related

c++ lock_free_queue example tested more slowly than mutex

i tested the example in book <C++ Concurrency in Action> charpter 7 lock_free_queue and mutex_queue by 2 threads push and 2 threads pop ,the result is using mutex is faster than lock_free queue.here is the lock_free queue code.
so anyone can explain this result? on x86 cpu, the head and tail respectively of lock_free_queue is mutex free,so my first thought is this lock_free_queue will faster than mutex_queue .
here is the mutex queue code:
template<typename T>
class LockFreeQueue
{
public:
struct Node;
struct CountedNodePtr{
int external_count;
Node* ptr;
CountedNodePtr()noexcept:external_count(0),ptr(nullptr){}
};
std::atomic<CountedNodePtr> head;
std::atomic<CountedNodePtr> tail;
struct NodeCounter{
uint32_t internal_count:30;
uint32_t external_counters:2;
};
struct Node{
std::atomic<T*> data;
std::atomic<NodeCounter> count;
CountedNodePtr next;
Node()noexcept{
NodeCounter new_count;
new_count.external_counters = 2;
new_count.internal_count = 0;
count.store(new_count);
data.store(nullptr);
}
void ReleaseRef(){
NodeCounter old_counter = count.load(std::memory_order_relaxed);
NodeCounter new_counter;
do{
new_counter = old_counter;
--new_counter.internal_count;
}while(!count.compare_exchange_strong(old_counter, new_counter,
std::memory_order_acquire,std::memory_order_relaxed));
if(!new_counter.internal_count && !new_counter.external_counters){
delete this;
}
}
};
static void IncreaseExternalCount(std::atomic<CountedNodePtr>& counter,
CountedNodePtr& old_counter){
CountedNodePtr new_counter;
do{
new_counter = old_counter;
++new_counter.external_count;
}while(!counter.compare_exchange_strong(old_counter, new_counter,
std::memory_order_acquire,std::memory_order_relaxed));
old_counter.external_count = new_counter.external_count;
}
static void FreeExternalCounter(CountedNodePtr& old_node_ptr){
Node* const ptr = old_node_ptr.ptr;
int const count_increase = old_node_ptr.external_count-2;
NodeCounter old_counter = ptr->count.load(std::memory_order_relaxed);
NodeCounter new_counter;
do{
new_counter = old_counter;
--new_counter.external_counters;
new_counter.internal_count+=count_increase;
}while(!ptr->count.compare_exchange_strong(old_counter, new_counter,
std::memory_order_acquire,std::memory_order_relaxed));
if(!new_counter.internal_count && !new_counter.external_counters){
delete ptr;
}
}
public:
LockFreeQueue(){
CountedNodePtr ptr ;
ptr.external_count =1;
ptr.ptr = new Node;
head.store(ptr);
tail.store(head.load());
};
~LockFreeQueue(){
while(Node* const old_head = head.load().ptr){
head.store(old_head->next);
delete old_head;
}
}
void Push(T new_value){
std::unique_ptr<T> new_data = std::make_unique<T>(new_value);
CountedNodePtr new_next;
new_next.ptr = new Node;
new_next.external_count = 1;
CountedNodePtr old_tail = tail.load();
for(;;){
IncreaseExternalCount(tail,old_tail);
T* old_data = nullptr;
if(old_tail.ptr->data.compare_exchange_strong(old_data,
new_data.get())){
old_tail.ptr->next = new_next;
old_tail = tail.exchange(new_next);
FreeExternalCounter(old_tail);
new_data.release();
break;
}
old_tail.ptr->ReleaseRef();
}
}
std::unique_ptr<T> Pop(){
CountedNodePtr old_head = head.load(std::memory_order_relaxed);
for(;;){
IncreaseExternalCount(head,old_head);
Node* const ptr = old_head.ptr;
if(ptr==tail.load().ptr){
ptr->ReleaseRef();
return std::unique_ptr<T>();
}
if(head.compare_exchange_strong(old_head, ptr->next)){
T* const res = ptr->data.exchange(nullptr);
FreeExternalCounter(old_head);
return std::unique_ptr<T>(res);
}
ptr->ReleaseRef();
}
}
};
// here is the mutex_queue
template <typename T>
class ThreadSafeQueue {
public:
ThreadSafeQueue() {}
ThreadSafeQueue& operator=(const ThreadSafeQueue& other) = delete;
ThreadSafeQueue(const ThreadSafeQueue& other) = delete;
~ThreadSafeQueue() { BreakAllWait(); }
void Enqueue(const T& element) {
std::lock_guard<std::mutex> lock(mutex_);
queue_.emplace(element);
// cv_.notify_one();
}
bool Dequeue(T* element) {
std::lock_guard<std::mutex> lock(mutex_);
if (queue_.empty()) {
return false;
}
*element = std::move(queue_.front());
queue_.pop();
return true;
}
// bool WaitDequeue(T* element) {
// std::unique_lock<std::mutex> lock(mutex_);
// cv_.wait(lock, [this]() { return break_all_wait_ || !queue_.empty(); });
// if (break_all_wait_) {
// return false;
// }
// *element = std::move(queue_.front());
// queue_.pop();
// return true;
// }
typename std::queue<T>::size_type Size() {
std::lock_guard<std::mutex> lock(mutex_);
return queue_.size();
}
bool Empty() {
std::lock_guard<std::mutex> lock(mutex_);
return queue_.empty();
}
void BreakAllWait() {
break_all_wait_ = true;
// cv_.notify_all();
}
private:
volatile bool break_all_wait_ = false;
std::mutex mutex_;
std::queue<T> queue_;
struct Node{
int data;
Node * next;
Node(const int& d):data(d),next(NULL){}
};
// std::condition_variable cv_;
};
// test code added here
#include <iostream>
#include "lock_free_queue.h"
#include "thread_safe_queue.h"
#include "unbounded_queue.h"
#include <thread>
#include <chrono>
#include <thread>
#include <atomic>
#include <vector>
#include <mutex>
#include <utility>
#include <iomanip>
#include <ucontext.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>
//#include <stdatomic.h>
#include <pthread.h>
#include <time.h>
#ifndef MDC_TEST
using namespace rudder::base;
using namespace apollo::cyber::base;
using namespace std;
struct Student
{
int a;
double b;
float c;
};
typedef int swr_ele_t; // 元素
int cycles;
typedef struct swr_queue
{ // 队列结构
std::atomic<size_t> head;
std::atomic<size_t> tail;
swr_ele_t *eles;
size_t size;
pthread_mutex_t lock;
} swr_queue_t;
LockFreeQueue<swr_ele_t> lock_queue_test[7];
ThreadSafeQueue<swr_ele_t> mutex_queue_test[7];
UnboundedQueue<swr_ele_t> unbounde_queue_test[7];
bool LockPush(const swr_ele_t *ele,int i)
{
lock_queue_test[i].Push(*ele);
return true;
};
bool LockPop(swr_ele_t *ele,int i)
{
auto tmp = lock_queue_test[i].Pop();
if(tmp == nullptr)
{
return false;
}
else
{
*ele = *tmp;
// std::cout<<"tmp"<<*tmp<<std::endl;
return true;
}
};
bool MutexPush(const swr_ele_t *ele,int i)
{
mutex_queue_test[i].Enqueue(*ele);
return true;
};
bool MutexPop(swr_ele_t *ele,int i)
{
swr_ele_t tmp;
if(mutex_queue_test[i].Dequeue(&tmp))
{
*ele = tmp;
return true;
}else{
return false;
}
};
bool UnboundedPush(const swr_ele_t *ele,int i)
{
unbounde_queue_test[i].Enqueue(*ele);
return true;
};
bool UnboundedPop(swr_ele_t *ele,int i)
{
swr_ele_t tmp;
if(unbounde_queue_test[i].Dequeue(&tmp))
{
*ele = tmp;
return true;
}else{
return false;
}
};
/***************************测试程序部分******************************/
typedef bool (*push_fn_t)(const swr_ele_t *,int);
typedef bool (*pop_fn_t)(swr_ele_t *,int);
// 线程参数
typedef struct thead_arg
{
//swr_queue_t *queue;
char type;
push_fn_t push;
pop_fn_t pop;
double push_time;
double pop_time;
int i;
} thead_arg_t;
// 计时器: 毫秒
double time_diff(struct timespec *start, struct timespec *end)
{
long sec = end->tv_sec - start->tv_sec;
long nsec = end->tv_nsec - start->tv_nsec;
return sec * 1000.0 + nsec / 1000000.0;
}
void *thread_func(void *a)
{
thead_arg_t *arg = (thead_arg_t *)a;
//swr_queue_t *queue = arg->queue;
struct timespec time1, time2;
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &time1);
if (arg->type == 'W')
{ // Producer
swr_ele_t e = cycles;
while (true)
{
if (arg->push(&e,arg->i))
{
if ((--e) < 0)
break;
}
}
}
else
{ // Consumer
while (true)
{
swr_ele_t e;
// cout<<"arg->pop"<<std::endl;
if (arg->pop(&e,arg->i))
{
// cout<<"pop"<<e <<std::endl;
// if (e % 1000000 == 0) printf("pop ele: %d\n", e);
if (e == 0)
break;
}
}
}
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &time2);
if(arg->type == 'W')
{
arg->push_time = time_diff(&time1, &time2);
}
else
{
arg->pop_time = time_diff(&time1, &time2);
}
printf("%c %d Time=%fms\n", arg->type, arg->i,time_diff(&time1, &time2));
// printf("%f ", arg->type, time_diff(&time1, &time2));
return NULL;
}
int main(int argc, char const *argv[])
{
// std::cout<<"argv"<< argv[1]<<std::endl;;
std::cout<<"core_num is : "<<std::thread::hardware_concurrency()<<std::endl;
std::cout<<"lock free head" <<lock_queue_test[0].head.is_lock_free()<<std::endl;
std::cout<<"lock free tail" <<lock_queue_test[0].tail.is_lock_free()<<std::endl;
int num = 0;
while(num<7)
{
cycles = 10000;
struct test_case
{
push_fn_t push;
pop_fn_t pop;
const char *desc;
} cases[] = {
//{LockPush, LockPop, "LockPush, LockPop"},
{MutexPush, MutexPop, "MutexPush,MutexPop"},
// {UnboundedPush, UnboundedPop, "UnboundedPush,UnboundedPop"},
};
for (unsigned int k = 0; k < sizeof(cases) / sizeof(cases[0]); ++k)
{
printf("----------------------------------------------------------------------------\n");
printf("%s\n", cases[k].desc);
swr_queue_t queue;
const int NUM = 6;
pthread_t tids[NUM];
thead_arg_t args[NUM];
int i;//0 1 2 3
// for (i = 0; i < NUM; ++i)
// {
// args[i].i = num;
// // args[i].queue = &queue;
// args[i].type = (i+1)%2 == 1 ? 'W' : 'R';
// args[i].push = cases[k].push;
// args[i].pop = cases[k].pop;
//// printf("pthread_create start");
// pthread_create(&tids[i], NULL, thread_func, args + i);
// }
for (i = 0; i < 3; ++i)
{
args[i].i = num;
// args[i].queue = &queue;
args[i].type = 'W';
args[i].push = cases[k].push;
args[i].pop = cases[k].pop;
// printf("pthread_create start");
pthread_create(&tids[i], NULL, thread_func, args + i);
// pthread_join(tids[i], NULL);
// printf("pthread_create %d",args[i].i);
}
for (i = 0; i < 3; ++i)
{
pthread_join(tids[i], NULL);
}
for (i = 3; i < 6; ++i)
{
args[i].i = num;
// args[i].queue = &queue;
args[i].type = 'R';
args[i].push = cases[k].push;
args[i].pop = cases[k].pop;
// printf("pthread_create start");
pthread_create(&tids[i], NULL, thread_func, args + i);
// pthread_join(tids[i], NULL);
// printf("pthread_create %d",args[i].i);
}
for (i = 3; i < 6; ++i)
{
pthread_join(tids[i], NULL);
}
printf("\n");
// printf("total time=%fms\n", args[0].push_time + args[1].pop_time);
// printf("%f\n", args[0].push_time + args[1].pop_time);
}
num++;
}
return 0;
}
#endif /* MDC_TEST */

Printing from Trie

I have built a trie in C++ designed to hold words of sentences. Each sentence will have a weight which determines the order in which they should be output. I have several recursive functions that call other recursive functions, and the dilemma I am facing is that I want to print my list only once.
Basically my get function calls the printFromNode function which creates the vector of pairs p that I want to sort and print. If someone could point me in the right direction in how to do that it would be much appreciated.
Code:
Trie.cpp:
//#include "Trie.h"
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <sstream>
#include <stack>
using namespace std;
class Node
{
private:
string word = "";
bool endOfSentence = false;
int weight = -1;
public:
vector<Node> children = {};
Node() {
this->setWord("");
}
Node(string s){
this->setWord(s);
}
string getWord(){
return this->word;
}
void setWord(string s) {
this->word = s;
}
void setEOS(){
this->endOfSentence = true;
}
void setWeight(int weight){
this->weight = weight;
}
int getWeight() {
return this->weight;
}
};
class Trie
{
public:
Node root;
void add(vector<string> phrase, int weight, Node* n){
Node* current = n;
int w = weight;
int found = -1;
for (int i = 0; i < current->children.size(); i++) {
if (phrase[0] == current->children[i].getWord()) {
found = i;
}
}
if (found > -1) {
current = &current->children[found];
phrase.erase(phrase.begin());
add(phrase, w, current);
}
else {
addPhrase(phrase, w, current);
}
}
void addPhrase(vector<string> phrase, int weight, Node* n) {
Node* current = n;
for (int i = 0; i < phrase.size(); i++) {
Node temp = *new Node(phrase[i]);
current->children.push_back(temp);
current = &current->children.back();
if (i == phrase.size() - 1) {
current->setEOS();
current->setWeight(weight);
}
}
}
void get(vector<string> search) {
Node* current = &this->root;
get(search, current);
}
void get(vector<string> search, Node* n) {
Node* current = n;
int found = -1;
//test search size
if (search.size() == 0) {
cout << "Please enter a valid search" << endl;
}
for (int i = 0; i < current->children.size(); i++) {
if (search[0] == current->children[i].getWord()) {
found = i;
}
}
if (found > -1 && search.size() == 1) {
current = &current->children[found];
printFromNode(*current);
maxNode(*current);
}
else if (found > -1 && search.size() != 1) {
current = &current->children[found];
search.erase(search.begin());
get(search, current);
}
else {
cout << "Not Found" << endl;
}
}
void printOutput(vector<pair<int,string>> p){
sort(p.begin(), p.end());
cout << p.size() << endl;
for (int i = 0; i < p.size(); i++) {
cout << p[i].second << " " << endl;
}
}
void printFromNode(Node n) {
vector<string> phrase = {};
vector <pair < int, string>> final = {};
printFromNode(n,phrase,final);
}
void printFromNode(Node n, vector<string> &v, vector<pair<int,string>> &p) {
string output;
if (n.getWord() == "") {
return;
}
for (int i = 0; i < n.children.size(); i++) {
if (n.children[i].getWeight() > 0) {
for (int i = 0; i < v.size(); i++)
{
output.append(v[i] + " ");
}
output.append(n.children[i].getWord());
p.push_back(make_pair(n.children[i].getWeight(), output));
}
v.push_back(n.children[i].getWord());
printFromNode(n.children[i], v, p);
v.pop_back();
sort(p.begin(), p.end());
}
return;
}
void maxNode(Node n) {
int max = 0;
int index = 0;
int temp = 0;
for (int i = 0; i < n.children.size(); i++) {
temp = n.children[i].children.size();
if (temp > max) {
max = temp;
index = i;
}
}
cout << n.children[index].getWord() << " " << max << endl;
}
};
Main.cpp:
#include "Trie.cpp"
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
int main(int argc, char* argv[]) {
// Initialize trie up here
Trie myTrie = *new Trie();
// parse input lines until I find newline
for(string line; getline(cin, line) && line.compare(""); ) {
stringstream ss(line);
string string_weight;
ss >> string_weight;
int weight = stoi(string_weight);
// I am just going to put these words into a vector
// you probably want to put them in your trie
vector<string> phrase = {};
for(string word; ss >> word;) {
phrase.push_back(word);
}
myTrie.add(phrase, weight, &myTrie.root);
vector<string> ans = {};
}
// parse query line
string query;
getline(cin, query);
stringstream ss(query);
vector<string> search = {};
for (string query; ss >> query;) {
search.push_back(query);
}
myTrie.get(search);
return 0;
}
You can remove recursive methods, and doing something like the following:
#include <algorithm>
#include <iostream>
#include <map>
#include <string>
#include <vector>
#include <set>
class Node
{
public:
bool endOfSentence = false;
std::set<int> weights;
std::map<std::string, Node> children;
Node() = default;
const Node* get(const std::string& word) const
{
auto it = children.find(word);
if (it == children.end()) {
return nullptr;
}
return &it->second;
}
auto find_by_weight(int weight) const
{
return std::find_if(children.begin(),
children.end(),
[=](const auto& p){ return p.second.weights.count(weight);});
}
};
class Trie
{
Node root;
public:
void add(int weight, const std::vector<std::string>& phrase)
{
Node* node = &root;
for (const auto& word : phrase) {
node->weights.insert(weight);
node = &node->children[word];
}
node->weights.insert(weight);
node->endOfSentence = true;
}
bool contains(const std::vector<std::string>& phrase) const
{
const Node* node = &root;
for (const auto& word : phrase) {
node = node->get(word);
if (node == nullptr) {
return false;
}
}
return node->endOfSentence;
}
void print(int weight) const
{
const Node* node = &root;
const char* sep = "";
while (node) {
const auto it = node->find_by_weight(weight);
if (it == node->children.end()) {
break;
}
std::cout << sep << it->first;
sep = " ";
node = &it->second;
}
std::cout << std::endl;
}
void print_all() const
{
for (int i : root.weights) {
print(i);
}
}
};
And usage/Test:
int main(int argc, char* argv[]) {
const std::vector<std::vector<std::string>> sentences = {
{"My", "name", "is", "John"},
{"My", "house", "is", "small"},
{"Hello", "world"},
{"Hello", "world", "!"}
};
Trie trie;
int i = 0;
for (const auto& sentence : sentences) {
trie.add(i, sentence);
++i;
}
const std::vector<std::vector<std::string>> queries = {
{"My", "name", "is", "John"},
{"My", "house"},
{"Hello", "world"}
};
for (const auto& query : queries) {
std::cout << trie.contains(query) << std::endl;
}
trie.print_all();
}
Demo

How to insert pair<string, CUSTOM_CLASS> into multimap C++

How can I insert pair<string, CUSTOM_CLASS> into multimap? pair() function is answering "no instance of constructor..."
What am I doing wrong?
MY code:
using namespace std;
class CUSTOM_CLASS{
public:
string state;
multimap<string, CUSTOM_CLASS> relation;
bool isStart = false;
bool isEnd = false;
}
CUSTOM_CLASS findNext(string s) {
for (int i = 0; i < automat.size(); i++) {
if (automat.at(i).stav == s) {
return automat.at(i);
}
}
}
void assignRelation(string f, string i, string w) {
multimap<string, CUSTOM_CLASS> tmp;
CUSTOM_CLASS where;
for (int i = 0; i < automat.size(); i++) {
if (automat.at(i).stav == f) {
where = findNext(w);
tmp.insert(pair<string, CUSTOM_CLASS>(i, where));
}
}
}
And this gives me error.

This sudoku solver runs for a very long time and I don't know why

I am trying to run this program but it just runs for a very long time when it is supposed to only take a couple seconds. I would appreciate it if I could get help on what is wrong with my code and what i need to fix.
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include "sudoku_solver.hpp"
int main()
{
std::vector< std::vector<int> > board(9,std::vector<int>(9));
int i =0,j=0;
for(std::string line;std::getline(std::cin,line);)
{
if(i==9)
{
i=0;
break;
}
std::stringstream line_stream(line);
for(std::string token;std::getline(line_stream,token,' ');)
{
if(j==9)
{
j=0;
}
board[i][j] = std::stoi(token);
j++;
}
i++;
}
if(sudoku_backtracker(board)==1)
{
for(int i = 0;i<9;i++)
{
for(int j = 0;j<9;j++)
{
std::cout<<board[i][j];
}
std::cout<<endl;
}
}
return 0;
}
sudoku_solver.hpp:
#ifndef __SUDOKU_SOLVER_HPP__
#define __SUDOKU_SOLVER_HPP__
#include <vector>
int sudoku_backtracker(std::vector< std::vector<int> > &board);
std::pair<int, int> find_empty_spot(std::vector< std::vector<int> > board);
bool checks_num_is_valid(std::vector< std::vector<int> > board,int row,int column,int number);
#endif //__SUDOKU_SOLVER_HPP__
sudoku_solver.cpp:
#include "sudoku_solver.hpp"
#include <iostream>
#include <string>
int sudoku_backtracker(std::vector< std::vector<int> > &board)
{
int test_num = 1;
std::pair<int,int> empty_spot = find_empty_spot(board);
if(empty_spot.first == -1)
{
return 1;
}
while(test_num != 10)
{
if(checks_num_is_valid(board,empty_spot.first,empty_spot.second,test_num))
{
board[empty_spot.first][empty_spot.second] = test_num;
int recursive_sudoku = sudoku_backtracker(board);
if(recursive_sudoku==1)
{
return 1;
}
board[empty_spot.first][empty_spot.second] = 0;
}
test_num++;
}
return 0;
}
std::pair<int, int> find_empty_spot(std::vector< std::vector<int> > board)
{
for(int row=0;row<9;row++)
{
for(int column=0;column<9;column++)
{
if(board[row][column] == 0){return std::make_pair(row,column);}
}
}
return std::make_pair(-1,-1);
}
bool checks_num_is_valid(std::vector< std::vector<int> > board, int row,int column, int number)
{
bool num_not_in_column = true;
bool num_not_in_row = true;
bool num_not_in_box = true;
//box_start_row as bsr and box_start_column as bsc
//this is the starting point to check the numbers inside the box and make
//sure the test number is valid
int bsr = 0,bsc = 0;
//checks the numbers in the same column but different rows
for(int i =0;i<9;i++)
{
if(i==row){continue;}
if(board[i][column] == number){num_not_in_column = false;break;}
}
//checks numbers in the same row but different columns
for(int i = 0;i<9;i++)
{
if(i==column){continue;}
if(board[row][i] == number){num_not_in_row = false;break;}
}
//checks wether the numer is int the same box
if(row<=2){bsr =0;}
if(row>=3 && row<=5){bsr = 3;}
if(row>=6 && row<=8){bsr = 6;}
if(column <=2){bsc =0;}
if(column>=3 && column<=5){bsc=3;}
if(column>=6 && column<=8){bsc=6;}
//double for loop to check all the values inside the box
for(bsr;bsr<bsr+3;bsr++)
{
for(bsc;bsc<bsc+3;bsc++)
{
if(bsr==row && bsc==column)
{continue;}
else
{
if(board[bsr][bsc] == number)
{
num_not_in_box = false;
}
}
}
}
bool result = num_not_in_row && num_not_in_column && num_not_in_box;
return result;
}
You have two nested infinite loops. bsr<bsr+3 is always true, regardless of bsr value. Except when it overflows, but that's undefined behaviour and the compiler is allowed to optimize that to true.
for(bsr;bsr<bsr+3;bsr++)
{
for(bsc;bsc<bsc+3;bsc++)

Why I can not output paths of the maze?Who can tell me?Please

about data structures,why i can't output paths of the maze? I use the stack to storage the information of the current position.Read map of maze through a text file,if the position cant't pass
will be marker by "#",it is a wall.the way marker by "+". written in C++.
PS:My English is very poor.
//stack.h
#ifndef _STACK_H_
#define _STACK_H_
#include<iostream>
#include<stdlib.h>
const int SIZE = 81;
using namespace std;
typedef struct
{
int x;
int y;
}PosType;
typedef struct SElemType{
int ord;//steps
PosType seat;//coordinate
int di;//direction
}SElemType;
typedef struct SqStack{
SElemType *base;
SElemType *top;
int StackSize;
}SqStack;
void Init_S(SqStack &S)
{
S.base = new SElemType[SIZE];
if(!S.base)
exit(EXIT_FAILURE);
S.top = S.base;
S.StackSize = SIZE;
}
bool StackEmpty(SqStack S)
{
if(S.top = S.base)
return true;
return false;
}
void Push(SqStack &S,SElemType e)
{
SElemType *newbase;
if(S.top-S.base>=S.StackSize)
{
newbase = new SElemType[S.StackSize*2];
if(!S.base)
exit(EXIT_FAILURE);
for(int i(0);i<S.top-S.base;i++)
*(newbase+i) = *(S.base+i);
delete[]S.base;
S.base = newbase;
S.top = S.base+S.StackSize;
S.StackSize *= 2;
}
*(S.top)++ = e;
}
void Pop(SqStack &S,SElemType e)
{
if(StackEmpty(S))
cout<<"empty stack!\n";
else
e = *(--S.top);
}
#endif
//maze.cpp
#include<iostream>
#include<cstdlib>
#include<fstream>
#include"stack.h"
using namespace std;
const int m = 10;
const int n = 10;
typedef char MazeG[m][n];
void Show_MG(MazeG MG)
{
for(int i(0);i<m;i++)
{
for(int j(0);j<n;j++)
{
cout<<MG[i][j];
}
cout<<"\t\n";
}
}
PosType Next(PosType &pos,int di)
{
PosType repos;
switch(di)
{
case 0://north
repos.x = pos.x-1;
repos.y = pos.y;
break;
case 1://east
repos.x = pos.x;
repos.y = pos.y+1;
break;
case 2://south
repos.x = pos.x+1;
repos.y = pos.y;
break;
case 3://west
repos.x = pos.x;
repos.y = pos.y-1;
break;
default:
break;
}
return repos;
}
int MazePath(MazeG &MG,PosType begin,PosType end)
{
PosType curpos = begin;
SqStack S;
Init_S(S);
SElemType e;
e.ord = 0;
do{
if(MG[curpos.x][curpos.y]=='*')
{
MG[curpos.x][curpos.y] = '+';
e.seat = curpos;
e.di = 0;
e.ord++;
Push(S,e);
if(curpos.x==end.x&&curpos.y==end.y)
{
cout<<"此迷宫的一条路径如下:(+标记为路径)\n";//the path of maze:
cout<<"走了"<<e.di<<"步到达出口\n";//The number of steps walked
Show_MG(MG);
return 0;
}
else
curpos = Next(curpos,e.di);
}
else
if(!StackEmpty(S))
{
Pop(S,e);
e.ord--;
while(e.di==3&&!StackEmpty(S))
{
MG[curpos.x][curpos.y] = '#';
Pop(S,e);
e.ord--;
}
if(e.di<3)
{
e.di++;
Push(S,e);
e.ord++;
curpos = Next(curpos,e.di);
}
}
}while(!StackEmpty(S));
cout<<"此迷宫没有入口到出口的路径!\n";//no path of the maze
//return -1;
}
int main()
{
MazeG MG;
PosType begin,end;
begin.x = 1; begin.y = 1;
end.x = 8; end.y = 8;
ifstream fin;
fin.open("file.txt");
if(!fin.is_open())
{
cout<<"erorr file!!\n";
exit(EXIT_FAILURE);
}
if(fin.good())
{
for(int i(0);i<m;i++)
for(int j(0);j<n;j++)
fin>>MG[i][j];
}
cout<<"迷宫图为:(*代表能通过)\n";//map of maze:('*' is means through)
Show_MG(MG);
cout<<begin.x<<begin.y<<end.x<<end.y<<endl;
fin.close();
MazePath(MG,begin,end);
return 0;
}
This is wrong
bool StackEmpty(SqStack S)
{
if(S.top = S.base)
return true;
return false;
}
It should be this
bool StackEmpty(SqStack S)
{
if(S.top == S.base) // == not =
return true;
return false;
}
Use == for equality not =.
Now,I understand my the error of code is that I mismatch the data will be stored by stack.
I have changed my code,that's right.
//stack.h
SElemType Gettop(SqStack S)
{
if(!Empty_S(S))
return *(S.top-1);
}
//maze_path.cpp
do{
if(MG[curpos.x][curpos.y]=='*')
{
MG[curpos.x][curpos.y] = '+';
e.seat = curpos;
e.di = 0;
e.ord++;
Push(S,e);
if(curpos.x==end.x&&curpos.y==end.y)
{
cout<<"此迷宫的一条路径如下:(+标记为路径)\n";//the path of maze:
cout<<"走了"<<e.di<<"步到达出口\n";//The number of steps walked
Show_MG(MG);
return 0;
}
else
curpos = Next(curpos,e.di);
}
else
if(!StackEmpty(S))
{
if(e.di<3)
{
e.ord++;
curpos = Next(curpos,e.di);
}
else
{
MG[curpos.x][curpos.y] = '#';
Pop(S,e);
e = Gettop(S);
}
}
}while(!StackEmpty(S));