Created
February 6, 2012 18:24
-
-
Save makokal/1753877 to your computer and use it in GitHub Desktop.
Simple cycle check in singly linked list (was part of SDE code interview)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Simple Singly Linked List | |
* Demonstrating check for cycles by remembering all visited nodes | |
* | |
* Using BOOST::Unordered_map as a hash table implementation | |
* | |
* \author Billy Okal | |
*/ | |
#include <iostream> | |
#include <boost/unordered_map.hpp> | |
using namespace std; | |
// A simple singly linked list node | |
class SNode | |
{ | |
public: | |
SNode() { next = NULL; } | |
virtual ~SNode() {} | |
void SetData(int aData) { data = aData; } | |
void SetNext(SNode *aNext) { next = aNext; } | |
int Data() { return data; } | |
SNode* Next() { return next; } | |
private: | |
int data; | |
SNode* next; | |
}; | |
// A simple singly linked list | |
class SList | |
{ | |
public: | |
SList() { head = NULL; } | |
virtual ~SList() {} | |
// print the list | |
void Print() | |
{ | |
SNode *tmp = head; | |
if ( tmp == NULL ) { | |
cout << "EMPTY" << endl; | |
return; | |
} | |
if ( tmp->Next() == NULL ) { | |
cout << tmp->Data(); | |
cout << " -> "; | |
cout << "NULL" << endl; | |
} | |
else { | |
do { | |
cout << tmp->Data(); | |
cout << " -> "; | |
tmp = tmp->Next(); | |
} | |
while ( tmp != NULL ); | |
cout << "NULL" << endl; | |
} | |
} | |
// append a member to the list | |
void Append(int data) | |
{ | |
SNode* newNode = new SNode(); | |
newNode->SetData(data); | |
newNode->SetNext(NULL); | |
SNode* tmp = head; | |
if ( tmp != NULL ) { | |
while ( tmp->Next() != NULL ) { | |
tmp = tmp->Next(); | |
} | |
tmp->SetNext(newNode); | |
} | |
else { | |
head = newNode; | |
} | |
} | |
void MakeCycle() | |
{ | |
// make a simple cycle | |
SNode* tmp = head; | |
// move till the end and connect to the first | |
if ( tmp != NULL ) { | |
while ( tmp->Next() != NULL ) { | |
tmp = tmp->Next(); | |
} | |
tmp->SetNext(head); | |
} | |
else {} | |
} | |
SNode* Begin() const { return head; } | |
private: | |
SNode* head; | |
}; | |
//overload hash_values | |
bool operator==(SNode n1, SNode n2) | |
{ | |
return n1.Next() == n2.Next(); | |
} | |
std::size_t hash_value(SNode n) { | |
std::size_t seed = 0; | |
boost::hash_combine(seed, n.Data()); | |
boost::hash_combine(seed, n.Data()); | |
return seed; | |
} | |
// Check for cycles in a singly linked list | |
int CheckCycles(SList _list) | |
{ | |
SNode* node = _list.Begin(); | |
int cycle = 0; | |
boost::unordered_map<SNode,int> hs; | |
boost::unordered_map<SNode,int>::iterator it; | |
while (node != NULL) { | |
it = hs.find( (*node) ); | |
if(it == hs.end() ) { | |
hs.insert(boost::unordered_map<SNode,int>::value_type((*node),node->Data())); | |
node = node->Next(); | |
} | |
else { | |
cycle = 1; | |
break; | |
} | |
} | |
return cycle; | |
} | |
int main(int argc, char** argv) | |
{ | |
//make a list and populate it | |
SList no_cycle_list; | |
no_cycle_list.Append(1); | |
no_cycle_list.Append(2); | |
no_cycle_list.Append(3); | |
no_cycle_list.Append(4); | |
no_cycle_list.Append(5); | |
no_cycle_list.Print(); | |
cout << "Cycle check before inserting cycle " << CheckCycles(no_cycle_list) << endl; | |
// make a cycle | |
no_cycle_list.MakeCycle(); | |
cout << "Cycle check after inserting cycle " << CheckCycles(no_cycle_list) << endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment