#include <bits/stdc++.h>
using namespace std;
template <typename T>
struct Node{
T info;
Node *link;
};
template<typename T>
class single_LinkedList{
private:
Node<T>* head;
int list_size ;
public:
single_LinkedList(){
assert(head);
head = nullptr;
list_size = 0;
}
void insertAtHead(int value){
Node<T>* newNode;
assert(newNode);
newNode = new Node<T>;
newNode->info = value;
///
newNode->link = head;
head = newNode;
list_size++;
}
void insertAtTail(int value){
Node<T>* newNode = new Node<T>;
assert(newNode);
newNode = new Node<T>;
newNode->info = value;
newNode->link = nullptr;
/// Make head point to the newNode element
if(head == nullptr){
head= newNode;
} else{
Node<T> *current ;
current = new Node<T>;
assert(current);
current = head;
while (current->link != nullptr){
current = current->link;
}
current->link = newNode;
}
list_size++;
}
void insertAt(T value , int index){
try {
if (index >= list_size || index < 0) {
throw std::runtime_error("Index out of bounds\n");
}
} catch (const std::runtime_error& e) {
std::cerr << "Exception caught: " << e.what() << std::endl;
}
if(index==0){
insertAtHead(value);
} else if(index == list_size - 1){
insertAtTail(value);
} else {
Node<T> *CurrentNode = new Node<T>;
assert(CurrentNode);
Node<T>*NewNode = new Node<T>;
assert(NewNode);
Node<T> *PrevNode = new Node<T>;
assert(PrevNode);
PrevNode->link = nullptr;
NewNode->info = value;
int current_index = 0;
CurrentNode = head;
while (current_index != index){
PrevNode = CurrentNode;
CurrentNode = CurrentNode->link;
current_index++;
}
PrevNode->link = NewNode;
NewNode->link = CurrentNode;
}
list_size++;
}
void removeAtTail(){
try {
if (isEmpty()) {
throw std::runtime_error("Empty list: Can't delete an element.\n");
}
} catch (const std::runtime_error& e) {
std::cerr << "Exception caught: " << e.what() << std::endl;
}
Node<T> *to_delete ;
to_delete = new Node<T>;
assert(to_delete);
to_delete = head;
while (to_delete->link != nullptr){
to_delete = to_delete->link;
}
Node<T>* before_delete;
before_delete = new Node<T>;
assert(before_delete);
before_delete = head;
while (before_delete->link != to_delete){
before_delete = before_delete->link;
}
delete to_delete;
before_delete->link = nullptr;
list_size--;
}
void removeAtHead(){
try {
if (isEmpty()) {
throw std::runtime_error("Empty list: Can't delete an element.\n");
}
} catch (const std::runtime_error& e) {
std::cerr << "Exception caught: " << e.what() << std::endl;
}
Node<T>*PointToHeadLink = new Node<T>;
assert(PointToHeadLink);
PointToHeadLink = head;
head = head->link;
delete PointToHeadLink;
list_size--;
}
void removeAt(int index){
try {
if (isEmpty()) {
throw std::runtime_error("Empty list: Can't delete an element.\n");
}
} catch (const std::runtime_error& e) {
std::cerr << "Exception caught: " << e.what() << std::endl;
}
try{
if(index < 0 || index >= list_size ){
throw std::runtime_error("Index out of bound :(.");
}
}catch (const std::runtime_error &e) {
cerr << "Exception caught " << e.what() << '\n';
}
Node<int>* current_node = head;
assert(current_node);
Node<int>* previous_current = new Node<int>;
assert(current_node);
previous_current->link = nullptr;
int current_index = -1;
while (current_index < index-1){
previous_current = current_node;
current_node = current_node->link;
current_index++;
}
if(previous_current->link == nullptr){
head = head->link;
delete current_node;
} else if(current_node->link == nullptr){
previous_current->link = nullptr;
delete current_node;
}
else {
previous_current->link = current_node->link;
delete current_node ;
}
list_size--;
}
T retrieveAt(int index)const{
try{
if(index < 0 || index >= list_size){
throw std::runtime_error("Index out of bound :(.");
}
}catch (const std::runtime_error &e) {
cerr << "Exception caught " << e.what() << '\n';
}
Node<int>* current_node = head;
assert(current_node);
Node<int>* previous_current = new Node<int>;
assert(previous_current);
previous_current->link = nullptr;
int current_index = -1;
while (current_index < index-1){
previous_current = current_node;
current_node = current_node->link;
current_index++;
}
if(previous_current->link == nullptr){
return head->info;
} else {
return current_node->info;
}
}
void replaceAt( T value , int index ){
try{
if(index < 0 || index >= list_size){
throw std::runtime_error("Index out of bound :(.");
}
}catch (const std::runtime_error &e) {
cerr << "Exception caught " << e.what() << '\n';
}
Node<int>* current_node = head;
assert(current_node);
Node<int>* previous_current = new Node<int>;
assert(previous_current);
previous_current->link = nullptr;
int current_index = -1;
while (current_index < index-1){
previous_current = current_node;
current_node = current_node->link;
current_index++;
}
if(previous_current->link == nullptr){
head->info = value;
} else {
current_node->info = value;
}
}
bool is_itemAt_equal( T value , int index )const{
try{
if(index < 0 || index >= list_size){
throw std::runtime_error("Index out of bound :(.");
}
}catch (const std::runtime_error &e) {
cerr << "Exception caught " << e.what() << '\n';
}
Node<int>* current_node = head;
assert(current_node);
Node<int>* previous_current = new Node<int>;
assert(previous_current);
previous_current->link = nullptr;
int current_index = -1;
while (current_index < index-1){
previous_current = current_node;
current_node = current_node->link;
current_index++;
}
if(previous_current->link == nullptr){
return head->info == value;
} else {
return current_node->info == value;
}
}
void swap(int first_index , int second_index){
try{
if(first_index < 0 || first_index >= list_size || second_index < 0 || second_index >= list_size){
throw std::runtime_error("Index out of bound :(.");
}
}catch (const std::runtime_error &e) {
cerr << "Exception caught " << e.what() << '\n';
}
Node<T>*current_node = head;
assert(current_node);
int current_index = 0;
while (current_index != first_index){
current_node = current_node->link;
current_index++;
}
Node<T>*first_node = current_node;
assert(first_node);
current_node = head;
current_index = 0;
while (current_index != second_index){
current_node = current_node->link;
current_index++;
}
Node<T>*second_node = current_node;
assert(second_node);
int temp = first_node->info;
first_node->info = second_node->info;
second_node->info = temp;
}
T size()const{
return list_size;
}
void print()const{
try {
if (isEmpty()) {
throw std::runtime_error("Empty list: Can't delete an element.\n");
}
} catch (const std::runtime_error& e) {
std::cerr << "Exception caught: " << e.what() << std::endl;
}
Node<T>* current = head;
assert(current);
while (current->link != nullptr){
cout << current->info << ' ';
current = current->link;
}
cout << current->info << '\n';
}
bool isEmpty()const{
return (head == nullptr);
}
void clear(){
if(head != nullptr){
Node<T> *current = new Node<T>;
assert(current);
current = head;
while (current != nullptr) {
Node<T> *temp = new Node<T>;
temp = current;
current = current->link;
delete temp;
}
}
head = nullptr;
list_size = 0;
}
~single_LinkedList(){
if(head != nullptr) {
Node<T> *current = new Node<T>;
assert(current);
current = head;
while (current->link != nullptr) {
Node<T> *temp = new Node<T>;
assert(temp);
temp = current;
current = current->link;
delete temp;
}
head = nullptr;
}
}
};
template<typename T>
class circular_LinkedList{
private:
Node<T>*head;
int list_size = 0;
public:
circular_LinkedList(){
head = new Node<T>;
assert(head);
head = nullptr;
list_size = 0;
}
void insertAtHead(int value){
Node<T>* newNode = new Node<T>;
assert(newNode);
newNode->info = value;
newNode->link = nullptr;
if(head == nullptr){
head = newNode;
head->link = head;
} else{
Node<T>*temp = new Node<T>;
temp = head;
newNode->link = head;
head = newNode;
Node<T>*current = head;
do{
current = current->link;
} while (temp != current->link);
current->link = head;
}
list_size++;
}
void insertAtTail(int value){
Node<T>* newNode = new Node<T>;
assert(newNode);
newNode = new Node<T>;
newNode->info = value;
newNode->link = nullptr;
/// Make head point to the newNode element
if(head == nullptr){
head = newNode;
} else{
Node<T> *current ;
current = new Node<T>;
assert(current);
current = head;
while (current->link != head){
current = current->link;
}
current->link = newNode;
newNode->link = head;
}
list_size++;
}
void insertAt(T value , int index){
try {
if (index >= list_size || index < 0) {
throw std::runtime_error("Index out of bounds\n");
}
} catch (const std::runtime_error& e) {
std::cerr << "Exception caught: " << e.what() << std::endl;
}
if(index==0){
insertAtHead(value);
} else if(index == list_size - 1){
insertAtTail(value);
} else {
Node<T> *CurrentNode = new Node<T>;
assert(CurrentNode);
Node<T>*NewNode = new Node<T>;
assert(NewNode);
Node<T> *PrevNode = new Node<T>;
assert(PrevNode);
PrevNode->link = head;
NewNode->info = value;
int current_index = 0;
CurrentNode = head;
while (current_index != index){
PrevNode = CurrentNode;
CurrentNode = CurrentNode->link;
current_index++;
}
NewNode->link = CurrentNode;
PrevNode->link = NewNode;
list_size++;
}
}
void removeAtTail(){
try {
if (isEmpty()) {
throw std::runtime_error("Empty list: Can't delete an element.\n");
}
} catch (const std::runtime_error& e) {
std::cerr << "Exception caught: " << e.what() << std::endl;
}
Node<T> *to_delete , *previous_delete = new Node<T>;
to_delete = new Node<T>;
assert(to_delete);
previous_delete->link = head;
to_delete = head;
while (to_delete->link != head){
previous_delete = to_delete;
to_delete = to_delete->link;
}
if(to_delete == head){
head = nullptr;
delete to_delete;
} else{
previous_delete->link = head;
delete to_delete;
}
list_size--;
}
void removeAtHead(){
try {
if (isEmpty()) {
throw std::runtime_error("Empty list: Can't delete an element.\n");
}
} catch (const std::runtime_error& e) {
std::cerr << "Exception caught: " << e.what() << std::endl;
}
Node<T>*temp = head;
if(temp->link == nullptr){
delete temp;
head = nullptr;
} else{
head = head->link;
Node<T>*current = head;
while (current->link != temp){
current = current->link;
}
current->link = head;
delete temp;
}
list_size--;
}
void removeAt(int index){
try {
if (isEmpty()) {
throw std::runtime_error("Empty list: Can't delete an element.\n");
}
} catch (const std::runtime_error& e) {
std::cerr << "Exception caught: " << e.what() << std::endl;
}
try{
if(index < 0 || index >= list_size ){
throw std::runtime_error("Index out of bound :(.");
}
}catch (const std::runtime_error &e) {
cerr << "Exception caught " << e.what() << '\n';
}
Node<int>* current_node = head;
assert(current_node);
Node<int>* previous_current = new Node<int>;
assert(current_node);
previous_current->link = nullptr;
int current_index = -1;
while (current_index < index-1){
previous_current = current_node;
current_node = current_node->link;
current_index++;
}
if(previous_current->link == nullptr){
head = head->link;
delete current_node;
} else if(current_node->link == head){
previous_current->link = nullptr;
delete current_node;
}
else {
previous_current->link = current_node->link;
delete current_node ;
}
list_size--;
}
T retrieveAt(int index)const{
try{
if(index < 0 || index >= list_size){
throw std::runtime_error("Index out of bound :(.");
}
}catch (const std::runtime_error &e) {
cerr << "Exception caught " << e.what() << '\n';
}
Node<int>* current_node = head;
assert(current_node);
Node<int>* previous_current = new Node<int>;
assert(previous_current);
previous_current->link = nullptr;
int current_index = 0;
while (current_index != index){
previous_current = current_node;
current_node = current_node->link;
current_index++;
}
if(previous_current->link == nullptr){
return head->info;
} else {
return current_node->info;
}
}
void replaceAt( T value , int index ){
try{
if(index < 0 || index >= list_size){
throw std::runtime_error("Index out of bound :(.");
}
}catch (const std::runtime_error &e) {
cerr << "Exception caught " << e.what() << '\n';
}
Node<int>* current_node = head;
assert(current_node);
Node<int>* previous_current = new Node<int>;
assert(previous_current);
previous_current->link = nullptr;
int current_index = -1;
while (current_index < index-1){
previous_current = current_node;
current_node = current_node->link;
current_index++;
}
if(previous_current->link == nullptr){
head->info = value;
} else {
current_node->info = value;
}
}
bool is_itemAt_equal( T value , int index )const{
try{
if(index < 0 || index >= list_size){
throw std::runtime_error("Index out of bound :(.");
}
}catch (const std::runtime_error &e) {
cerr << "Exception caught " << e.what() << '\n';
}
Node<int>* current_node = head;
assert(current_node);
Node<int>* previous_current = new Node<int>;
assert(previous_current);
previous_current->link = nullptr;
int current_index = -1;
while (current_index < index-1){
previous_current = current_node;
current_node = current_node->link;
current_index++;
}
if(previous_current->link == nullptr){
return head->info == value;
} else {
return current_node->info == value;
}
}
void swap(int first_index , int second_index){
try{
if(first_index < 0 || first_index >= list_size || second_index < 0 || second_index >= list_size){
throw std::runtime_error("Index out of bound :(.");
}
}catch (const std::runtime_error &e) {
cerr << "Exception caught " << e.what() << '\n';
}
if(first_index == second_index)
return;
int mx = max(first_index , second_index);
int mn = min(first_index , second_index);
first_index = mn;
second_index = mx;
Node<T>*first_node = new Node<T>;
Node<T>*before_first_node = new Node<T>;
before_first_node->link = nullptr;
Node<T>*second_node = new Node<T>;
Node<T>*before_second_node = new Node<T>;
before_second_node->link = nullptr;
first_node = head;
int cnt = 0;
while (cnt < first_index){
before_first_node = first_node;
first_node = first_node->link;
cnt++;
}
second_node = head;
cnt = 0;
while (cnt < second_index){
before_second_node = second_node;
second_node = second_node->link;
cnt++;
}
Node<T>*temp2 = new Node<T>;
Node<T>*temp1 = new Node<T>;
if (first_node == head) {
temp2 = second_node->link;
temp1 = second_node;
temp1->link = first_node;
first_node->link = temp2;
} else if (second_node == head) {
// If second_node is the head of the list
temp1->link = second_node->link; // Save the link of second_node
temp1 = first_node;
before_first_node->link = temp2;
temp2->link = first_node->link;
temp2 = first_node;
head = temp2; // Update the head if necessary
} else {
temp2 = second_node->link;
first_node->link = temp2;
before_first_node->link = second_node;
second_node->link = first_node;
}
}
T size()const{
return list_size;
}
void print()const{
try {
if (isEmpty()) {
throw std::runtime_error("Empty list: Can't delete an element.\n");
}
} catch (const std::runtime_error& e) {
std::cerr << "Exception caught: " << e.what() << std::endl;
}
Node<T>*current = head;
do{
cout << current->info << ' ';
current = current->link;
} while (current != head);
cout << '\n';
}
bool isEmpty()const{
return (head == nullptr);
}
void clear(){
if(head != nullptr){
Node<T> *current = new Node<T>;
assert(current);
current = head;
while (current != head) {
Node<T> *temp = new Node<T>;
temp = current;
current = current->link;
delete temp;
}
}
head = nullptr;
list_size = 0;
}
~circular_LinkedList() {
if (head != nullptr) {
Node<T>* current = head;
Node<T>* next;
do {
next = current->link;
delete current;
current = next;
} while (current != head);
head = nullptr;
list_size = 0;
}
}
};
int main(){
circular_LinkedList<int>list1;
list1.insertAtHead(5);
list1.insertAtHead(6);
list1.insertAtHead(7);
list1.insertAtTail(1);
list1.insertAtTail(2);
list1.insertAtTail(3);
list1.swap(0 , 1);
// 7 6 5 1 2 3
// 6 7 5 1 2 3
list1.print();
}