Bogotobogo
contact@bogotobogo.com
- C++ Home
- String
- Constructor
- Operator Overloading
- Virtual Functions
- Dynamic Cast Operator
- Type Cast Operators
- Class auto_ptr
- References for Built-in Types
- Pass by Value vs. Pass by Reference
- Memory Allocation
- Friend Functions and Friend Classes
- Functors (Function Objects)
- Static Variables and Static Class Members
- Exceptions
- Stack Unwinding
- Pointers
- Pointers II - void pointers & arrays
- Pointers III - pointer to function & multi-dimensional arrays
- Taste of Assembly
- Small Programs
- Linked List Examples
- Binary Tree Example Code
- Templates
- Standard Template Library (STL) I
- Standard Template Library (STL) II - Maps
- Standard Template Library (STL) III - Iterators
- Standard Template Library (STL) IV - Algorithms
- Object Slicing and Virtual Table
- The this Pointer
- Stack Unwinding
- Upcasting and Downcasting
- Object Returning
- Private Inheritance
- Preprocessor - Macro
- C++_Keywords
- fstream: input & output
- Multi-Threaded Programming - Terminology
- Multi-Threaded Programming II - Native Thread for Win32 (A)
- Multi-Threaded Programming II - Native Thread for Win32 (B)
- Multi-Threaded Programming II - Native Thread for Win32 (C)
- Multi-Threaded Programming II - C++ Thread for Win32
- Multi-Threaded Programming III - C++ Class Thread for Pthreads
- Multithread Debugging
- Socket - Server & Client
- Embedded Systems Programming
- Boost
- make
- Debugging Crash & Memory Leak
- Libraries
- C++ API Testing
- Design Patterns in C++
- Algorithms in C++
- Programming Questions and Solutions
- Blackjack with Qt
A linked list is a basic data structure where each item contains the information that we need to get to the next item. The main advantage of linked lists over arrays is that the links provide us with the capability to rearrange the item efficiently. This flexibility is gained at the expense of quick access to any arbitrary item in the list, because the only way to access to an item in the list is to follow links from the beginning.
The following examples are for the linked list. Inside each example, we have several operations:
- Reversing the linked list (#1, #3, #4)
- Copying the linked list(#1)
- Detecting circular (loop) linked list(#5)
- Comparing the two linked list(#1)
- Deleting the linked list(#1)
- Adding, deleting, inserting, and searching a node (all examples)
- Stack implementation with linked list (#6, #7)
- Finding intersection and union of two lists (#8)
- Example 1
When the head of the list is not a global pointer. - Example 2 and Example 3
When the head of the list is a global pointer.
There are some implementation differences between these two examples. - Example 4
Used class & structure in that class. - Example 5A
Detecting circular (loop) linked list. - Example 5B
Detecting circular (loop) linked list (Generic Class with Template). - Example 6
Stack with linked list data structure. - Example 7
Class Stack with linked list data structure. - Example 8
Queue with linked list data structure. - Example 9
Finding intersection and union of two linked lists. - Example 10
Generic linked lists.
Also, there is another set of linked list quiz.
#include <iostream>
using namespace std;
struct Node {
int data;
Node* next;
};
// only for the 1st Node
void initNode(struct Node *head,int n){
head->data = n;
head->next =NULL;
}
// apending
void addNode(struct Node *head, int n) {
Node *newNode = new Node;
newNode->data = n;
newNode->next = NULL;
Node *cur = head;
while(cur) {
if(cur->next == NULL) {
cur->next = newNode;
return;
}
cur = cur->next;
}
}
void insertFront(struct Node **head, int n) {
Node *newNode = new Node;
newNode->data = n;
newNode->next = *head;
*head = newNode;
}
struct Node *searchNode(struct Node *head, int n) {
Node *cur = head;
while(cur) {
if(cur->data == n) return cur;
cur = cur->next;
}
cout << "No Node " << n << " in list.\n";
}
bool deleteNode(struct Node **head, Node *ptrDel) {
Node *cur = *head;
if(ptrDel == *head) {
*head = cur->next;
delete ptrDel;
return true;
}
while(cur) {
if(cur->next == ptrDel) {
cur->next = ptrDel->next;
delete ptrDel;
return true;
}
cur = cur->next;
}
return false;
}
/* reverse the list */
struct Node* reverse(struct Node** List)
{
Node *parent = *List;
Node *me = parent->next;
Node *child = me->next;
/* make parent as tail */
parent->next = NULL;
while(child) {
me->next = parent;
parent = me;
me = child;
child = child->next;
}
me->next = parent;
*List = me;
return *List;
}
/* Creating a copy of a linked list */
void copyLinkedList(struct Node *node, struct Node **pNew)
{
if(node != NULL) {
*pNew = new Node;
(*pNew)->data = node->data;
(*pNew)->next = NULL;
copyLinkedList(node->next, &((*pNew)->next));
}
}
/* Compare two linked list */
/* return value: same(1), different(0) */
int compareLinkedList(struct Node *node1, struct Node *node2)
{
static int flag;
/* both lists are NULL */
if(node1 == NULL && node2 == NULL) {
flag = 1;
}
else {
if(node1 == NULL || node2 == NULL)
flag = 0;
else if(node1->data != node2->data)
flag = 0;
else
compareLinkedList(node1->next, node2->next);
}
return flag;
}
void deleteLinkedList(struct Node **node)
{
struct Node *tmpNode;
while(*node) {
tmpNode = *node;
*node = tmpNode->next;
delete tmpNode;
}
}
void display(struct Node *head) {
Node *list = head;
while(list) {
cout << list->data << " ";
list = list->next;
}
cout << endl;
cout << endl;
}
int main()
{
struct Node *newHead;
struct Node *head = new Node;
initNode(head,10);
display(head);
addNode(head,20);
display(head);
addNode(head,30);
display(head);
addNode(head,35);
display(head);
addNode(head,40);
display(head);
insertFront(&head,5);
display(head);
int numDel = 5;
Node *ptrDelete = searchNode(head,numDel);
if(deleteNode(&head,ptrDelete))
cout << "Node "<< numDel << " deleted!\n";
display(head);
cout << "The list is reversed\n";
reverse(&head);
display(head);
cout << "The list is copied\n";
copyLinkedList(head,&newHead);
display(newHead);
cout << "Comparing the two lists...\n";
cout << "Are the two lists same?\n";
if(compareLinkedList(head,newHead))
cout << "Yes, they are same!\n";
else
cout << "No, they are different!\n";
cout << endl;
numDel = 35;
ptrDelete = searchNode(newHead,numDel);
if(deleteNode(&newHead,ptrDelete)) {
cout << "Node "<< numDel << " deleted!\n";
cout << "The new list after the delete is\n";
display(newHead);
}
cout << "Comparing the two lists again...\n";
cout << "Are the two lists same?\n";
if(compareLinkedList(head,newHead))
cout << "Yes, they are same!\n";
else
cout << "No, they are different!\n";
cout << endl;
cout << "Deleting the copied list\n";
deleteLinkedList(&newHead);
display(newHead);
return 0;
}
Output from the run:
10 10 20 10 20 30 10 20 30 35 10 20 30 35 40 5 10 20 30 35 40 Node 5 deleted! 10 20 30 35 40 The list is reversed 40 35 30 20 10 The list is copied 40 35 30 20 10 Comparing the two lists... Are the two lists same? Yes, they are same! Node 35 deleted! The new list after the delete is 40 30 20 10 Comparing the two lists again... Are the two lists same? No, they are different! Deleting the copied list
#include <iostream>
using namespace std;
struct node {
int data;
struct node * next;
};
node *head = NULL;
// returning the pointer to the element
// whose data is less than or equal to input data
struct node *searchNode(int n) {
if(head == NULL) return head;
node *cur = head;
node *prev = head;
while(cur) {
if(cur->data == n) return cur;
if(cur->data > n) return prev;
prev = cur;
cur = cur->next;
}
}
// returning the pointer to the element
// whose data is equal to input data
struct node *searchNode2(int n) {
if(head == NULL) return head;
node *cur = head;
node *prev = head;
while(cur) {
if(cur->data == n) return cur;
prev = cur;
cur = cur->next;
}
return cur;
}
void addNode(int n) {
node *newNode = new node;
newNode->data = n;
newNode->next = NULL;
if(head == NULL) {
head = newNode;
return;
}
node *cur = head;
while(cur) {
if(cur->next == NULL) {
cur->next = newNode;
return;
}
cur = cur->next;
}
}
void insertNode(int n) {
node *ptr = searchNode(n);
node *newNode = new node;
newNode->data = n;
node *cur = head;
while(cur) {
if(cur == ptr ) {
newNode->next = cur->next;
cur->next = newNode;
return;
}
cur = cur->next;
}
}
void deleteNode(int n) {
node *ptr = searchNode(n);
if(ptr == NULL)
cout << "No node with data = " << n << endl;
if(ptr == head) {
head = ptr->next;
return;
}
node *cur = head;
node *prev = head;
while(cur) {
if(cur == ptr) {
prev->next = cur->next;
return;
}
prev = cur;
cur = cur->next;
}
}
void display() {
struct node *list = head;
while(list) {
cout << list->data <<" ";
list = list->next;
}
cout << endl;
}
int main()
{
addNode(10);
display();
addNode(20);
display();
addNode(40);
display();
addNode(50);
display();
insertNode(30);
display();
deleteNode(40);
display();
return 0;
}
// linked list example - using struct
#include <iostream>
#include <cstring>
using namespace std;
struct node * initNode( char *, int );
void displayNode( struct node * );
void displayList( struct node * );
void addNode( struct node * );
struct node * searchName( struct node *, char * );
void deleteNode( struct node * );
void insertNode( struct node * );
void deleteList( struct node * );
struct node {
char name[20];
int id;
struct node *next;
};
struct node *head = (struct node *) NULL;
struct node *tail = (struct node *) NULL;
// allocates memory for the node
// assign values to the member of the structure
struct node * initNode( char *name, int id )
{
struct node *ptr = new node;
// error? then just return
if( ptr == NULL )
return static_cast<struct node *>(NULL);
// assign it
// then return pointer to ne node
else {
strcpy( ptr->name, name );
ptr->id = id;
return ptr;
}
}
// adding to the end of list
void addNode( struct node *newnode )
{
// if there is no node, put it to head
if( head == NULL ) {
head = newnode;
tail = newnode;
}
// link in the new_node to the tail of the list
// then mark the next field as the end of the list
// adjust tail to point to the last node
tail->next = newnode;
newnode->next = NULL;
tail = newnode;
}
void insertNode( struct node *newnode )
{
struct node *temp, *prev;
if( head == NULL ) { // if an empty list,
head = newnode; // set 'head' to it
tail = newnode;
head->next = NULL; // set end of list to NULL
return;
}
temp = head; // start at beginning of list
// while currentname < newname
while( strcmp( temp->name, newnode->name) < 0 ) {
// to be inserted then
temp = temp->next; // goto the next node in list
if( temp == NULL ) // don't go past end of list
break;
}
// set previous node before we insert
// first check to see if it's inserting
if( temp == head ) { // before the first node
newnode->next = head; // link next field to original list
head = newnode; // head adjusted to new node
}
else { // it's not the first node
prev = head; // start of the list,
while( prev->next != temp ) { // will cycle to node before temp
prev = prev->next;
}
prev->next = newnode; // insert node between prev and next
newnode->next = temp;
if( tail == prev ) // if the new node is inserted at the
tail = newnode; // end of the list the adjust 'end'
}
}
struct node * searchName( struct node *ptr, char *name )
{
while( strcmp( name, ptr->name ) != 0 ) {
ptr = ptr->next;
if( ptr == NULL )
break;
}
return ptr;
}
struct node* searchId(struct node* ptr, int id) {
while( id != ptr->id ) {
ptr = ptr->next;
if( ptr == NULL )
break;
}
return ptr;
}
void reverse() {
// we need at least two nodes for the reverse to have any effect
if(head == NULL || head->next == NULL) return;
// Starting 2nd list as 'me' and 'head' is now 'me->next'
// and 'head->next' is pointing to NULL
// So, the 3rd list is now 'child' of 'me'
node *parent = head;
node *me = head->next;
node *child = me->next;
// convert head to tail
parent->next = NULL;
while(child != NULL){
me->next = parent;
parent = me;
me = child;
child = child->next;
}
// when me reached the tail
// me becomes head
head = me;
// the head is now pointing to the 2nd last node
head->next = parent;
}
void deleteNode( struct node *ptr )
{
struct node *temp, *prev;
temp = ptr; // node to be deleted
prev = head; // start of the list, will cycle to node before temp
if( temp == prev ) { // deleting first node?
head = head->next; // moves head to next node
if( tail == temp ) // is it end, only one node?
tail = tail->next; // adjust end as well
delete temp ; // free up space
}
else { // if not the first node, then
while( prev->next != temp ) { // move prev to the node before
prev = prev->next; // the one to be deleted
}
prev->next = temp->next; // link previous node to next
if( tail == temp ) // if this was the end node,
tail = prev; // then reset the end pointer
delete temp; // free up space
}
}
void deleteList( struct node *ptr )
{
struct node *temp;
if( head == NULL ) return; // don't try to delete an empty list
if( ptr == head ) { // if we are deleting the entire list
head = NULL; // then reset head and
tail = NULL; // end to empty
}
else {
temp = head; // if it's not the entire list, readjust end
while( temp->next != ptr ) // locate previous node to ptr
temp = temp->next;
tail = temp; // set end to node before ptr
}
while( ptr != NULL ) { // while there are still nodes to delete
temp = ptr->next; // record address of next node
delete ptr; // free this node
ptr = temp; // point to next node to be deleted
}
}
void displayNode( struct node *ptr ) {
cout << ptr->id << ": " << ptr->name << endl;
}
void displayList( struct node *ptr ) {
while( ptr != NULL ) {
displayNode( ptr );
ptr = ptr->next;
}
}
#include <iostream>
using namespace std;
int main()
{
char* name;
int id, ch = 1;
struct node *ptr;
// add
ptr = initNode( "s1", 1 );
addNode(ptr);
ptr = initNode( "s2", 2 );
addNode(ptr);
ptr = initNode( "s3", 3 );
addNode(ptr);
ptr = initNode( "s4", 4 );
addNode(ptr);
ptr = initNode( "s5", 5 );
addNode(ptr);
displayList(head);
// delete
name = "s2";
ptr = searchName(head, name );
if( ptr == NULL ) {
cout << "\nName: " << name << " not found" << endl;
}
else {
cout << "\nDeleting a node ... ";
displayNode(ptr);
deleteNode( ptr );
}
displayList(head);
// insert
name = "s2";
id = 2;
ptr = initNode( name, id );
insertNode( ptr );
cout << "\nInserting a node ... ";
displayNode(ptr);
displayList(head);
// reverse
cout << "\nReversing the list ... \n";
reverse();
displayList(head);
// delete
cout << "\nIn the end, deleting the list ... \n";
deleteList(head);
displayList(head);
return 0;
}
// linked list example - using struct inside a class
#include <iostream>
#include <string>
using namespace std;
class list
{
public:
struct node {
int id;
string name;
struct node *next;
} *head, *tail, *ptr;
list():head(NULL),tail(NULL){} // constructor
~list(); // destructor
struct list::node* searchName(struct list::node*, string);
struct list::node* searchId(struct list::node*, int);
struct list::node* initNode(string, int);
void reverse();
void addNode( struct list::node*);
void insertNode( struct list::node*);
void deleteNode( struct list::node*);
void deleteList( struct list::node*);
void displayList( struct list::node*)const ;
void displayNode( struct list::node*) const;
};
list::~list() {
node *current,*temp;
current = head;
temp = head;
while(current != NULL) {
current = current->next;
delete temp;
temp = current;
}
}
struct list::node* list::initNode(string s, int i) {
struct node *ptr = new node;
// error? then just return
if( ptr == NULL )
return static_cast<struct node *>(NULL);
// assign it
// then return pointer to ne node
else {
ptr->name = s ;
ptr->id = i;
return ptr;
}
}
// adding to the end of list
void list::addNode( struct node *newNode ) {
// if there is no node, put it to head
if( head == NULL ) {
head = newNode;
tail = newNode;
}
// link in the new_node to the tail of the list
// then mark the next field as the end of the list
// adjust tail to point to the last node
tail->next = newNode;
newNode->next = NULL;
tail = newNode;
}
void list::insertNode( struct node *newnode ) {
struct node *temp, *prev;
if( head == NULL ) { // if an empty list,
head = newnode; // set 'head' to it
tail = newnode;
head->next = NULL; // set end of list to NULL
return;
}
temp = head; // start at beginning of list
// while currentname < newname
while( temp->name < newnode->name) { // to be inserted then
temp = temp->next; // goto the next node in list
if( temp == NULL ) // don't go past end of list
break;
}
// set previous node before we insert
// first check to see if it's inserting
if( temp == head ) { // before the first node
newnode->next = head; // link next field to original list
head = newnode; // head adjusted to new node
}
else { // it's not the first node
prev = head; // start of the list,
while( prev->next != temp ) {
prev = prev->next; // will cycle to node before temp
}
prev->next = newnode; // insert node between prev and next
newnode->next = temp;
if( tail == prev ) // if the new node is inserted at the
tail = newnode; // end of the list the adjust 'end'
}
}
struct list::node* list::searchName(struct node* ptr, string name) {
while( name != ptr->name ) {
ptr = ptr->next;
if( ptr == NULL )
break;
}
return ptr;
}
struct list::node* list::searchId(struct node* ptr, int id) {
while( id != ptr->id ) {
ptr = ptr->next;
if( ptr == NULL )
break;
}
return ptr;
}
void list::reverse() {
// we need at least two nodes for the reverse to have any effect
if(head == NULL || head->next == NULL) return;
// Starting 2nd list as 'me' and 'head' is now 'me->next'
// and 'head->next' is pointing to NULL
// So, the 3rd list is now 'child' of 'me'
node *parent = head;
node *me = head->next;
node *child = me->next;
// convert head to tail
head->next = NULL;
// reverse pointer direction
me->next = head;
while(child != NULL){
me->next = parent;
parent = me;
me = child;
child = child->next;
}
// when me reached the tail
// me becomes head
head = me;
// the head is now pointing to the 2nd last node
head->next = parent;
}
void list::deleteNode( struct list::node *ptr )
{
struct node *temp, *prev;
temp = ptr; // node to be deleted
prev = head; // start of the list, will cycle to node before temp
if( temp == prev ) { // deleting first node?
head = head->next; // moves head to next node
if( tail == temp ) // is it end, only one node?
tail = tail->next; // adjust end as well
delete temp ; // free up space
}
else { // if not the first node, then
while( prev->next != temp ) { // move prev to the node before
prev = prev->next; // the one to be deleted
}
prev->next = temp->next; // link previous node to next
if( tail == temp ) // if this was the end node,
tail = prev; // then reset the end pointer
delete temp; // free up space
}
}
void list::deleteList( struct node *ptr )
{
struct node *temp;
if( head == NULL ) return; // don't try to delete an empty list
if( ptr == head ) { // if we are deleting the entire list
head = NULL; // then reset head and
tail = NULL; // end to empty
}
else {
temp = head; // if it's not the entire list, readjust end
while( temp->next != ptr ) // locate previous node to ptr
temp = temp->next;
tail = temp; // set end to node before ptr
}
while( ptr != NULL ) { // whilst there are still nodes to delete
temp = ptr->next; // record address of next node
delete ptr; // free this node
ptr = temp; // point to next node to be deleted
}
}
void list::displayNode( struct list::node *ptr ) const
{
cout << ptr->id << ": " << ptr->name << endl;
}
void list::displayList( struct list::node *ptr ) const
{
if(!ptr) cout << "Nothing to display" << endl;
while(ptr) {
displayNode(ptr);
ptr = ptr->next;
}
}
int main()
{
int id;
string name;
list myList;
list::node* ptr;
// add
ptr = myList.initNode( "s1", 1 );
myList.addNode(ptr);
ptr = myList.initNode( "s2", 2 );
myList.addNode(ptr);
ptr = myList.initNode( "s3", 3 );
myList.addNode(ptr);
ptr = myList.initNode( "s4", 4 );
myList.addNode(ptr);
ptr = myList.initNode( "s5", 5 );
myList.addNode(ptr);
myList.displayList(myList.head);
// delete
name = "s2";
ptr = myList.searchName( myList.head, name );
if( ptr == NULL ) {
cout << "\nName: " << name << " not found" << endl;
}
else {
cout << "\nDeleting a node ... ";
myList.displayNode(ptr);
myList.deleteNode( ptr );
}
myList.displayList(myList.head);
// insert
name = "s2";
id = 2;
ptr = myList.initNode( name, id );
myList.insertNode( ptr );
cout << "\nInserting a node ... ";
myList.displayNode(ptr);
myList.displayList(myList.head);
// reverse
cout << "\nReversing the list ... \n";
myList.reverse();
myList.displayList(myList.head);
// delete
cout << "\nIn the end, deleting the list ... \n";
myList.deleteList(myList.head);
myList.displayList(myList.head);
return 0;
}
/* This code has the following */
/*
1. Adding Nodes
2. Function returning the size of the list
3. Making the list circular (loop)
4. Detecting circular list
5. Recursive printing
*/
#include <iostream>
using namespace std;
struct Node
{
int data;
Node * next;
};
Node *root = 0;
void addNode(int n)
{
if(root==0) {
root = new Node;
root->data = n;
root->next = 0;
return;
}
Node *cur = root;
while(cur) {
if(cur->next == 0) {
Node *ptr = new Node;
ptr -> data = n;
ptr -> next = 0;
cur -> next = ptr;
return;
}
cur = cur->next;
}
}
void makeCircular()
{
if(!root || !root->next) return;
Node *cur = root;
while(cur) {
if(cur->next == 0) {
cur->next = root;
return;
}
cur = cur->next;
}
}
int sizeOfList()
{
Node *cur = root;
int size = 0;
while(cur) {
size++;
if(cur->next == 0) {
return size;
}
cur = cur->next;
}
return size;
}
bool detectCircular()
{
// Assuming the list may not be circular
if(!root || !root->next) return false;
Node *ptr1 = root;
Node *ptr2 = root;
while(ptr1 && ptr2) {
ptr1 = ptr1->next;
ptr2 = ptr2->next;
if(ptr2) {
ptr2 = ptr2->next;
if(!ptr2) return false;
}
else {
return false;
}
cout << ptr1->data << "," << ptr2->data << endl;
if(ptr1==ptr2) {
return true;
}
}
return false;
}
void printRecursive(Node *ptr)
{
if(!ptr) {
cout << endl;
return;
}
cout << ptr->data << " ";
printRecursive(ptr->next);
}
int main(int argc, char **argv)
{
addNode(10);addNode(20);addNode(30);addNode(40);addNode(50);
addNode(60);addNode(70);addNode(80);addNode(90);addNode(100);
printRecursive(root);
cout << "size of list = " << sizeOfList() << endl;
makeCircular();
if(detectCircular()) cout <<"Circular\n";
else cout << "Normal\n";
}
Output from the run:
10 20 30 40 50 60 70 80 90 100 size of list = 10 20,30 30,50 40,70 50,90 60,10 70,30 80,50 90,70 100,90 10,10 Circular
#include <iostream>
#include <string>
using namespace std;
template <class T>
class LinkedList
{
private:
struct node
{
T data;
node * next;
} *head;
public:
LinkedList();
~LinkedList();
void add(T d);
void remove(T d);
void clear();
void makeCircular();
bool isCircular();
void display(const char* s);
};
template <class T>
LinkedList<T>::LinkedList()
{
head = NULL;
}
template <class T>
LinkedList<T>::~LinkedList()
{
node *p, *q;
p = head;
if(p == NULL) return;
while(p) {
q = p->next;
delete p;
p = q;
}
}
template <class T>
void LinkedList<T>::add(T d)
{
node *p, *q;
if(head == NULL) {
head = new node;
head->data = d;
head->next = NULL;
return;
}
p = head;
while(p->next != NULL)
p = p->next;
q = new node;
q->data = d;
q->next = NULL;
p->next = q;
}
template <class T>
void LinkedList<T>::remove(T d)
{
node *p, *q;
if(head == NULL) return;
p = head;
while(p) {
if(p->data == d) {
q->next = p->next;
delete p;
return;
}
q = p;
p = p->next;
}
}
template <class T>
void LinkedList<T>::clear()
{
node *p, *q;
if(head == NULL) return;
p = head;
while(p) {
q = p->next;
delete p;
if(q != head) {
head = NULL;
return;
}
p = q;
}
}
template <class T>
void LinkedList<T>::makeCircular()
{
node *p;
if(head == NULL || head->next == NULL) return;
p = head;
while(p) {
if(p->next == NULL) {
p->next = head;
return;
}
p = p->next;
}
}
template <class T>
bool LinkedList<T>::isCircular()
{
node *p, *pp;
if(head == NULL || head->next == NULL) return false;
p = head;
pp = head;
while(pp) {
p = p->next;
if(pp->next == NULL) return false;
pp = (pp->next)->next;
if(p == pp) return true;
}
return false;
}
template <class T>
void LinkedList<T>::display(const char* s)
{
node *p;
if(head == NULL) return;
p = head;
while(p) {
if(s == "string")
cout << p->data << endl;
else
cout << p->data << ' ';
p = p->next;
if(p != NULL) {
if(p == head) return;
}
}
if(s == "integer") cout << endl;
}
int main()
{
LinkedList<string> sList;
sList.add("Wolfgang Amadeus Mozart");
sList.add("Franz Peter Schubert");
sList.add("Pyotr Ilyich Tchaikovsky");
sList.add("Clude-Achille Debussy");
sList.add("Camille Saint-Saens");
sList.display("string");
sList.clear();
LinkedList<int> iList;
iList.add(40);
iList.add(50);
iList.add(60);
iList.add(70);
iList.add(80);
iList.add(90);
iList.add(100);
iList.add(10);
iList.add(20);
iList.add(30);
iList.display("integer");
/* link last element to the first */
iList.makeCircular();
if(iList.isCircular()) cout <<"This is circular list\n";
iList.display("integer");
iList.clear();
cout << "\ndisplay after clear()\n";
iList.display("integer");
return 0;
}
Output from the run is:
Wolfgang Amadeus Mozart Franz Peter Schubert Pyotr Ilyich Tchaikovsky Clude-Achille Debussy Camille Saint-Saens 40 50 60 70 80 90 100 10 20 30 This is circular list 40 50 60 70 80 90 100 10 20 30 display after clear()
This stack is using linked list as its data structure.
/* Stack operations */
#include <iostream<
using namespace std;
typedef struct Element
{
void *data;
struct Element *next;
} Element;
bool push(Element **top, void *data)
{
Element *elem = new Element;
if(!elem) return false;
elem->data = data;
elem->next = *top;
*top = elem;
return true;
}
bool createStack(Element **top)
{
*top = NULL;
return true;
}
bool pop(Element **top, void **data )
{
Element *elem;
if( !(elem = *top) ) return false;
*data = elem->data;
*top = elem->next;
delete elem;
return true;
}
bool deleteStack(Element **top)
{
Element *elem;
while(*top) {
elem = (*top)->next;
delete *top;
*top = elem;
}
return true;
}
void printStack(Element *top)
{
if(top==NULL) {
cout << "Empty!" << endl;
}
Element *cur = top;
while(cur) {
cout << *(static_cast<int *>(cur->data)) << " ";
cur = cur->next;
}
cout << endl << endl;
}
int main()
{
Element *head;
createStack(&head);
int n1 = 10, n2 = 20, n3 = 30, n4 = 40, n5 = 50;
push(&head, &n1);
push(&head, &n2);
push(&head, &n3);
push(&head, &n4);
push(&head, &n5);
printStack(head);
void * n;
pop(&head, &n);
cout << "popped " << *(static_cast<int*>(n)) << endl;
pop(&head, &n);
cout << "popped " << *(static_cast<int*>(n)) << endl;
cout << endl;
printStack(head);
cout << "deleting stack..." << endl;
deleteStack(&head);
printStack(head);
}
The code below is almost the same as the code in Example 6 except it's using Stack class.
#include <iostream>
using namespace std;
class Stack
{
public:
Stack();
~Stack();
void push(void *data);
void *pop();
void print();
protected:
typedef struct Element {
struct Element *next;
void *data;
} Element;
Element *top;
};
Stack::Stack() {
top = NULL;
}
Stack::~Stack() {
while(top) {
Element *elm = top->next;
delete top;
top = elm;
}
}
void Stack::push(void *data) {
Element *elm = new Element;
elm->data = data;
elm->next = top;
top = elm;
}
void *Stack::pop() {
void *data;
if(top == NULL) return data;
data = top->data;
Element *elm = top;
top = elm->next;
delete elm;
return data;
}
void Stack::print() {
Element *elm = top;
while(elm) {
cout << *(static_cast<int*>(elm->data)) << " " ;
elm = elm->next;
}
cout << endl;
}
int main()
{
Stack *st = new Stack;
int n1 = 10;
int n2 = 20;
int n3 = 30;
int n4 = 40;
int n5 = 50;
st->push(&n1);
st->push(&n2);
st->push(&n3);
st->push(&n4);
st->push(&n5);
st->print();
cout << *(static_cast<int*>(st->pop()))<< " poped\n";
cout << *(static_cast<int*>(st->pop()))<< " poped\n";
st->print();
cout << endl;
}
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
node *next;
};
typedef struct node node_t;
node_t *head = NULL;
void push(int n)
{
node_t *newNode = (node_t *)malloc(sizeof(node_t));
newNode->data = n;
newNode->next = NULL;
if(head == NULL) {
head = newNode;
return;
}
node_t *cur = head;
while(cur) {
if(cur->next==NULL) {
cur->next = newNode;
return;
}
cur = cur->next;
}
}
void pop()
{
if(head==NULL) return;
node_t *tmp = head;
head = head->next;
free(tmp);
}
void display()
{
node_t *cur = head;
while(cur) {
printf("%3d",cur->data);
cur = cur->next;
}
printf("\n");
}
int main()
{
push(1);push(2);push(3);push(4);push(5);display();
pop();display();
pop();display();
pop();display();
pop();display();
pop();display();
return 0;
}
Output is:
1 2 3 4 5 2 3 4 5 3 4 5 4 5 5
The following code finds intersection/union of two linked list and puts it into a new linked list.
#include <iostream>
using namespace std;
struct node
{
int data;
node *next;
};
void add(struct node **head, int n)
{
struct node *cur;
struct node *new_node = (struct node *)malloc(sizeof(struct node));
new_node->data = n;
new_node->next = NULL;
if(*head == NULL) {
*head = new_node;
return;
}
cur = *head;
while(cur) {
if(cur->next == NULL) {
cur->next = new_node;
return;
}
cur = cur->next;
}
}
bool isDuplicate(struct node *head, int n)
{
struct node* cur = head;
while(cur) {
if(cur->data == n) return true;
cur = cur->next;
}
return false;
}
struct node *getIntersection(struct node *headA, struct node *headB)
{
struct node *curA = headA;
struct node *curB = headB;
struct node *result = NULL;
if(curA == NULL || curB == NULL) return NULL;
while(curA) {
while(curB) {
if(curA->data == curB->data) {
add(&result, curA->data);
}
curB = curB->next;
}
curB = headB;
curA = curA->next;
}
return result;
}
struct node *getUnion(struct node *headA, struct node *headB)
{
struct node *cur;
struct node *result = NULL;
if(headA == NULL && headB == NULL) return NULL;
cur = headA;
while(cur) {
add(&result, cur->data);
cur = cur->next;
}
cur = headB;
while(cur) {
/* check if the new data is already there */
if(!isDuplicate(result, cur->data)) {
add(&result, cur->data);
}
cur = cur->next;
}
return result;
}
void display(struct node *head)
{
if(head == NULL) return;
struct node *cur = head;
while(cur) {
cout << cur->data << ' ';
cur = cur->next;
}
cout << endl;
}
int main()
{
struct node *myListA = NULL;
struct node *myListB = NULL;
struct node *intersectionList = NULL;
struct node *unionList = NULL;
add(&myListA,10);
add(&myListA,20);
add(&myListA,30);
add(&myListA,40);
add(&myListA,50);
add(&myListA,60);
add(&myListA,70);
cout << "List A: ";
display(myListA);
add(&myListB,10);
add(&myListB,30);
add(&myListB,50);
add(&myListB,70);
add(&myListB,90);
add(&myListB,110);
add(&myListB,130);
cout << "List B: ";
display(myListB);
cout << "Intersection of A and B: ";
intersectionList = getIntersection(myListA, myListB);
display(intersectionList);
cout << "Union of A and B: ";
unionList = getUnion(myListA, myListB);
display(unionList);
return 0;
}
Output is:
List A: 10 20 30 40 50 60 70 List B: 10 30 50 70 90 110 130 Intersection of A and B: 10 30 50 70 Union of A and B: 10 20 30 40 50 60 70 90 110 130
The following example is another example of generic use of linked list. It will be used as a base for doubly linked list later.
#include <iostream>
using namespace std;
template <typename T>
class List
{
struct Node
{
T data;
Node *next;
Node(T d, Node *n = 0):data(d), next(n) {}
};
Node *head;
public:
List(Node *h = 0):head(h){}
~List();
void insert(Node *loc, T d);
void push_back(T d);
void push_front(T d);
T pop_back();
T pop_front();
void erase(Node *loc);
void display();
Node *search(T d);
};
// destructor
template <typename T>
List<T>::~List()
{
Node *tmp;
while(head) {
tmp = head;
head = head->next;
delete tmp;
}
}
// insert d before loc
template <typename T>
void List<T>::insert(Node *loc, T d)
{
Node *new_node = new Node(d,0);
if(!head) {
head = new_node;
return;
}
if(loc == head) {
push_front(d);
return;
}
Node *cur = head;
while(cur->next) {
if(cur->next == loc) {
new_node->next = cur->next;
cur->next = new_node;
return ;
}
cur = cur->next;
}
}
template <typename T>
void List<T>::push_back(T d)
{
Node *new_node = new Node(d,0);
if(!head) {
head = new_node;
return;
}
Node *cur = head;
while(cur) {
if(!cur->next) {
cur->next = new_node;
return;
}
cur = cur->next;
}
}
template <typename T>
void List<T>::push_front(T d)
{
Node *new_node = new Node(d,0);
if(!head) {
head = new_node;
return;
}
new_node->next = head;
head = new_node;
return;
}
template <typename T>
T List<T>::pop_back()
{
Node *cur = head;
while(cur) {
if(!cur->next) {
T data (cur->data);
delete cur;
head = NULL;
return data;
}
else {
if(!cur->next->next) {
T data (cur->next->data);
cur->next = NULL;
delete cur->next;
return data;
}
}
cur = cur->next;
}
return NULL;
}
template <typename T>
T List<T>::pop_front()
{
if(!head) return NULL;
Node *tmp = head;
T data (head->data);
if(head->next) {
head = head->next;
delete tmp;
return data;
}
delete tmp;
head = NULL;
return data;
}
template <typename T>
void List<T>::erase(Node *loc)
{
if(loc == head) {
Node *tmp = head;
head = head->next;
delete tmp;
return;
}
Node *cur = head;
while(cur) {
if(cur->next == loc) {
cur->next = loc->next;
delete loc;
}
cur = cur->next;
}
}
template <typename T>
typename List<T>::Node* List<T>::search(T d)
{
if(!head) return NULL;
Node* cur = head;
while(cur) {
if(cur->data == d) return cur;
cur = cur->next;
}
return NULL;
}
template <typename T>
void List<T>::display()
{
if(!head) return;
Node *cur = head;
while(cur) {
cout << cur->data << " " << endl;
cur = cur->next;
}
cout << endl;
}
int main()
{
List<int> *myList = new List<int>(NULL);
cout << "push_back() 20, 30 40, 50\n\n";
myList->push_back(20);
myList->push_back(30);
myList->push_back(40);
myList->push_back(50);
myList->display();
cout << "push_front() 10\n\n";
myList->push_front(10);
myList->display();
cout << "erase 30\n\n";
myList->erase(myList->search(30));
myList->display();
cout << "insert 30 before 40\n\n";
myList->insert(myList->search(40),30);
myList->display();
cout << "pop_back()\n";
cout << myList->pop_back() << " just back popped\n\n";
myList->display();
cout << "pop_front()\n";
cout << myList->pop_front() << " just front popped\n\n";
myList->display();
return 0;
}
- Example 1
When the head of the list is not a global pointer. - Example 2 and Example 3
When the head of the list is a global pointer.
There are some implementation differences between these two examples. - Example 4
Used class & structure in that class. - Example 5A
Detecting circular (loop) linked list. - Example 5B
Detecting circular (loop) linked list (Generic Class with Template). - Example 6
Stack with linked list data structure. - Example 7
Class Stack with linked list data structure. - Example 8
Queue with linked list data structure. - Example 9
Finding intersection and union of two linked lists. - Example 10
Generic linked lists.
Also, there is another set of linked list quiz.
- C++ Home
- String
- Constructor
- Operator Overloading
- Virtual Functions
- Dynamic Cast Operator
- Type Cast Operators
- Class auto_ptr
- References for Built-in Types
- Pass by Value vs. Pass by Reference
- Memory Allocation
- Friend Functions and Friend Classes
- Functors (Function Objects)
- Static Variables and Static Class Members
- Exceptions
- Stack Unwinding
- Pointers
- Pointers II - void pointers & arrays
- Pointers III - pointer to function & multi-dimensional arrays
- Taste of Assembly
- Small Programs
- Linked List Examples
- Binary Tree Example Code
- Templates
- Standard Template Library (STL) I
- Standard Template Library (STL) II - Maps
- Standard Template Library (STL) III - Iterators
- Standard Template Library (STL) IV - Algorithms
- Object Slicing and Virtual Table
- The this Pointer
- Stack Unwinding
- Upcasting and Downcasting
- Object Returning
- Private Inheritance
- Preprocessor - Macro
- C++_Keywords
- fstream: input & output
- Multi-Threaded Programming - Terminology
- Multi-Threaded Programming II - Native Thread for Win32 (A)
- Multi-Threaded Programming II - Native Thread for Win32 (B)
- Multi-Threaded Programming II - Native Thread for Win32 (C)
- Multi-Threaded Programming II - C++ Thread for Win32
- Multi-Threaded Programming III - C++ Class Thread for Pthreads
- Multithread Debugging
- Socket - Server & Client
- Embedded Systems Programming
- Boost
- make
- Debugging Crash & Memory Leak
- Libraries
- C++ API Testing
- Design Patterns in C++
- Algorithms in C++
- Programming Questions and Solutions
- Blackjack with Qt