-
doubly linked lists
hello,
while studying for our short tests, our tutor gave us this problem to complete telling us that if we could do this it would be great. problem is we havnt quiet covered the syllabus yet and yet its coming in the papers and we are xpected to learn on our own.
with a partially completed projet, we are supposed to finish it where by the user enters a country name, its region, economy, tourist arrivals, tourism rankings. together with this we are supposed to enter the name of the cities and state whether it is the capital city or not, the tourist arrival of the particular city, and if u can travel there by air.
i've done a lil bit but im really stuck.
find attached a document outlining the major implementations to be done and a graphical view of the linked lists. bt im truely confused til now. i cant seem to enter the data. templetes are used also.
can some1 please tel me what and how to do pliz?
here's what i've done so far. the main program and the country class implementation has to be completed. also in country class, this piece of code NODE<city> * _city, what do i have to do with this?
thanks
Code:
#include <iostream.h>
#include <stdlib.h>
#include <string>
using namespace std;
//------------------------------------------------------------------------
template <class T>
struct NODE {
NODE<T> *pNext;
NODE<T> *pPrev;
T nData;
};
template <class T>
void AppendNode(NODE<T> * pNode, NODE<T> **pHead, NODE<T> **pTail);
template <class T>
void InsertNode(NODE<T> *pNode, NODE<T> *pAfter, NODE<T> **pTail);
template <class T>
void InsertNodeAt(NODE<T> *pNode, NODE<T> *pAfter, NODE<T> **pHead);
template <class T>
void RemoveNode(NODE<T> *pNode, NODE<T> **pHead, NODE<T> **pTail);
template <class T>
void DeleteAllNodes(NODE<T> **pHead, NODE<T> **pTail);
template <class T>
void AppendNode(NODE<T> * pNode, NODE<T> **pHead, NODE<T> **pTail)
{
if (*pHead == NULL) {
*pHead = pNode;
pNode->pPrev = NULL;
}
else {
(*pTail)->pNext = pNode;
pNode->pPrev = *pTail;
}
*pTail = pNode;
pNode->pNext = NULL;
}
// Inserts a node into the list after pAfter
template <class T>
void InsertNode(NODE<T> *pNode, NODE<T> *pAfter, NODE<T> **pTail)
{
pNode->pNext = pAfter->pNext;
pNode->pPrev = pAfter;
if (pAfter->pNext != NULL)
pAfter->pNext->pPrev = pNode;
else
*pTail = pNode;
pAfter->pNext = pNode;
}
template <class T>
void InsertNodeAt(NODE<T> *pNode, NODE<T> *pAt, NODE<T> **pHead)
{
pNode->pNext = pAt;
pNode->pPrev = pAt->pPrev;
if (pAt->pPrev == NULL) //head
*pHead = pNode;
else
pAt->pPrev->pNext = pNode;
pAt->pPrev = pNode;
}
// Removes the specified node from the list
template <class T>
void RemoveNode(NODE<T> *pNode, NODE<T> **pHead, NODE<T> **pTail)
{
if (pNode->pPrev == NULL)
*pHead = pNode->pNext;
else
pNode->pPrev->pNext = pNode->pNext;
if (pNode->pNext == NULL)
*pTail = pNode->pPrev;
else
pNode->pNext->pPrev = pNode->pPrev;
delete pNode;
}
// Deletes the entire list
template <class T>
void DeleteAllNodes(NODE<T> **pHead, NODE<T> **pTail)
{
while (*pHead != NULL)
RemoveNode(*pHead, pHead, pTail);
}
//-------------------------------------------------------------------------
//------------------------------------------------------------------------------
class city{
public:
city();
~city();
string getName() const;
void setName(string name);
bool getIscapital() const;
void setIscapital(bool iscapital);
unsigned int getTourist_arrivals() const;
void setTourist_arrivals(unsigned int tourist_arrivals);
bool getTravel_by_air() const;
void setTravel_by_air(bool travel_by_air);
private:
string name;
bool iscapital;
unsigned int tourist_arrivals;
bool travel_by_air;
};
city::city() {
// TODO Auto-generated constructor stub
}
city::~city() {
// TODO Auto-generated destructor stub
}
string city::getName() const
{
return name;
}
void city::setName(string name)
{
this->name = name;
}
bool city::getIscapital() const
{
return iscapital;
}
void city::setIscapital(bool iscapital)
{
this->iscapital = iscapital;
}
unsigned int city::getTourist_arrivals() const
{
return tourist_arrivals;
}
void city::setTourist_arrivals(unsigned int tourist_arrivals)
{
this->tourist_arrivals = tourist_arrivals;
}
bool city::getTravel_by_air() const
{
return travel_by_air;
}
void city::setTravel_by_air(bool travel_by_air)
{
this->travel_by_air = travel_by_air;
}
//-----------------------------------------------------------------------------
class country {
public:
country();
virtual ~country();
string getName() const;
void setName(string name);
string getRegion() const;
void setRegion(string region);
string getEconomy() const;
void setEconomy(string economy);
unsigned int getTourist_arrivals() const;
void setTourist_arrivals(unsigned int tourist_arrivals);
int getTourism_ranking() const;
void setTourism_ranking(int tourism_ranking);
NODE<city> * _city;
private:
string name;
string region;
string economy;
unsigned int tourist_arrivals;
int tourism_ranking;
};
country::country() {
// TODO Auto-generated constructor stub
}
country::~country() {
// TODO Auto-generated destructor stub
}
string country::getName() const
{
return name;
}
void country::setName(string name)
{
this->name = name;
}
string country::getRegion() const
{
return region;
}
void country::setRegion(string region)
{
this->region = region;
}
string country::getEconomy() const
{
return economy;
}
void country::setEconomy(string economy)
{
this->economy = economy;
}
unsigned int country::getTourist_arrivals() const
{
return tourist_arrivals;
}
void country::setTourist_arrivals(unsigned int tourist_arrivals)
{
this->tourist_arrivals = tourist_arrivals;
}
int country:: getTourism_ranking()const
{
return tourism_ranking;
}
void country::setTourism_ranking(int tourism_ranking)
{
this->tourism_ranking = tourism_ranking;
}
//-----------------------------------------------------------------------------
int main(){
country details;
string value;
cout <<"enter country name ?"<<endl ;
cin >> value;
details.setName(value);
cout<<endl;
string reg;
cout<<"region?"<<endl;
cin>>reg;
details.setRegion(reg);
cout<<endl;
string eco;
cout<<"economy?"<<endl;
cin>>eco;
details.setEconomy(eco);
cout<<endl;
unsigned int ari;
cout<< "tourist arrivals"<<endl;
cin>>ari;
details.setTourist_arrivals(ari);
cout<<endl;
int rank;
cout<< "tourism ranking"<<endl;
cin>>rank;
details.setTourism_ranking(rank);
cout<<endl;
cout<<" country name: "<<details.getName()<<endl;
cout<<" region: "<<details.getRegion()<<endl;
cout<<" economy: "<<details.getEconomy()<<endl;
cout<<" tourist arrivals: "<<details.getTourist_arrivals()<<endl;
cout<<" tourism ranking: "<<details.getTourism_ranking()<<endl<<endl;
system("pause");
return 0;
}
Last edited by SpywareDr; 01-16-2018 at 01:19 PM.
Reason: Added [code][/code] tags
-
[Mod - would you add code tags to the code in post #1 so that it's readable!]
-
-
 Originally Posted by 2kaud
[Mod - would you add code tags to the code in post #1 so that it's readable!]
Done
-
The code concerning the list is a great example of how not to do it! Apart from using template<>, this is c code - not c++ code. This is definitely how you don't do it in c++. Considering that post #1 was posted Oct 2017 I am astounded that this sort of c++ coding is still taught and students expected to learn it and program likewise. The best advice I can give is for the teacher to take permanent gardening leave. My sympathy is with the students who think they are being taught c++ when they are not.
For a simple c++ doubly linked list consider
Code:
#include <iostream>
using namespace std;
template <typename T>
class dll {
public:
class dllIter;
dll() {}
~dll()
{
clear();
}
dll(const dll& l)
{
for (const auto& d : l)
insertTail(d);
}
dll(dll&& l)
{
swap(l);
}
dll(initializer_list<T> il)
{
for (const auto& d : il)
insertTail(d);
}
dll& operator=(const dll& l)
{
dll t(l);
swap(t);
return *this;
}
dll& operator=(dll&& l)
{
swap(l);
return *this;
}
void clear()
{
for (auto n = head; n;) {
auto d = n;
n = n->next;
delete d;
}
head = tail = nullptr;
}
void swap(dll& l)
{
std::swap(l.head, head);
std::swap(l.tail, tail);
std::swap(l.cnt, cnt);
}
size_t size() const
{
return cnt;
}
bool empty() const
{
return cnt == 0;
}
dllIter insert(const dllIter& it, const T& d)
{
auto t = new node;
t->data = d;
if (head == nullptr)
// Empty list
head = tail = t;
else
if (it == end()) {
// Insert at tail
t->prev = tail;
tail->next = t;
tail = t;
} else
if (it == begin()) {
//Insert at head
t->next = head;
head->prev = t;
head = t;
} else {
it->prev->next = t;
t->prev = it->prev;
it->prev = t;
t->next = it();
}
++cnt;
return dllIter(t);
}
dllIter insertHead(const T& d)
{
return insert(begin(), d);
}
dllIter insertTail(const T& d)
{
return insert(end(), d);
}
void remove(const dllIter& it)
{
if (head == nullptr)
return;
if (it == end() || (it()->next == nullptr)) {
// Remove from tail
auto t = tail;
if ((tail = tail->prev) == nullptr)
head = tail;
else
tail->next = nullptr;
delete t;
} else
if (it == begin() || (it()->prev == nullptr)) {
// Remove from head
auto h = head;
if ((head = head->next) == nullptr)
tail = head;
else
head->prev = nullptr;
delete h;
} else {
auto n = it();
n->prev->next = n->next;
n->next->prev = n->prev;
delete n;
}
--cnt;
}
void removeHead()
{
remove(begin());
}
void removeTail()
{
remove(end());
}
dllIter begin() const
{
return dllIter(head);
}
dllIter end() const
{
return dllIter();
}
dllIter rbegin() const
{
return dllIter(tail, false);
}
dllIter rend() const
{
return dllIter();
}
dllIter find(const T& d) const
{
for (auto i = begin(); i != end(); ++i)
if (d == *i)
return i;
return end();
}
private:
struct node {
T data;
node* prev = nullptr;
node* next = nullptr;
node() {}
};
node* head = nullptr;
node* tail = nullptr;
size_t cnt = 0;
};
template<typename Elem>
class dll<Elem>::dllIter {
public:
dllIter(node* p = nullptr, bool f = true) : curr(p), forward(f) {}
dllIter& operator++()
{
curr = (forward) ? curr->next : curr->prev;
return *this;
}
dllIter& operator--()
{
curr = (forward) ? curr->prev : curr->next;
return *this;
}
Elem& operator*() const { return curr->data; }
node* operator->() const {return curr;}
node* operator()() const {return curr;}
bool operator==(const dllIter& b) const { return curr == b.curr; }
bool operator!=(const dllIter& b) const { return !operator==(b); }
private:
node *curr = nullptr;
bool forward = true;
};
template<typename T>
void showlist(const dll<T>& dl)
{
for (auto it = dl.begin(); it != dl.end(); ++it)
cout << *it << endl;
cout << endl;
for (auto it = dl.rbegin(); it != dl.rend(); ++it)
cout << *it << endl;
cout << endl;
}
int main()
{
dll<int> mylist {1, 2, 3, 4, 5};
dll<int> l1(mylist);
for (const auto& d : l1)
cout << d << endl;
cout << endl;
auto i = mylist.find(3);
cout << *i << endl << endl;
mylist.insert(i, 8);
showlist(mylist);
mylist.removeHead();
showlist(mylist);
mylist.removeTail();
showlist(mylist);
auto i2 = mylist.find(3);
mylist.remove(i2);
showlist(mylist);
}
Note that this hasn't been extensively tested so there may be issues with some edge cases. If any are found, post a message.
Usage for city and country classes will follow.............
Last edited by 2kaud; 01-17-2018 at 01:42 PM.
-
Considering the original post, for a method of using the doubly linked lists for the countries and cities within countries together with a simple menu consider
Code:
class city {
public:
city() {}
city(const city& c) = default;
city(city&& c) = default;
city& operator=(const city& c) = default;
city& operator=(city&& c) = default;
string getName() const
{
return name;
}
void setName(const string& nam)
{
name = nam;
}
bool getIscapital() const
{
return iscapital;
}
void setIscapital(bool iscap)
{
iscapital = iscap;
}
unsigned int getTourist_arrivals() const
{
return tourist_arrivals;
}
void setTourist_arrivals(unsigned int arrivals)
{
tourist_arrivals = arrivals;
}
bool getTravel_by_air() const
{
return travel_by_air;
}
void setTravel_by_air(bool by_air)
{
travel_by_air = by_air;
}
private:
string name;
bool iscapital = false;
unsigned int tourist_arrivals = 0;
bool travel_by_air = false;
};
class country {
public:
country() {}
country(const country& c) = default;
country(country&& c) = default;
country& operator=(const country& c) = default;
country& operator=(country&& c) = default;
string getName() const
{
return name;
}
void setName(const string& nam)
{
name = nam;
}
string getRegion() const
{
return region;
}
void setRegion(const string& reg)
{
region = reg;
}
string getEconomy() const
{
return economy;
}
void setEconomy(const string& econ)
{
economy = econ;
}
unsigned int getTourist_arrivals() const
{
return tourist_arrivals;
}
void setTourist_arrivals(unsigned int arrivals)
{
tourist_arrivals = arrivals;
}
int getTourism_ranking() const
{
return tourism_ranking;
}
void setTourism_ranking(int ranking)
{
tourism_ranking = ranking;
}
void add_city(const city& cty)
{
cities.insertTail(cty);
}
void display_cities() const
{
for (const auto& c : cities)
cout << c.getName() << endl;
cout << endl;
}
auto find_city(const string& nam) const
{
for (auto i = cities.begin(); i != cities.end(); ++i)
if (i->data.getName() == nam)
return i;
return cities.end();
}
bool remove_city(const string& nam)
{
if (auto f = find_city(nam); f != cities.end()) {
cities.remove(f);
return true;
}
return false;
}
private:
string name;
string region;
string economy;
unsigned int tourist_arrivals = 0;
int tourism_ranking = 0;
dll<city> cities;
};
void get_country(country& ctrs)
{
string s;
cout << "Country name: ";
cin >> s;
ctrs.setName(s);
cout << "Region: ";
cin >> s;
ctrs.setRegion(s);
cout << "Economy: ";
cin >> s;
ctrs.setEconomy(s);
int a = 0;
cout << "Number of tourist arrivals: ";
if (!(cin >> a)) {
cin.clear();
cin.ignore(1000, '\n');
}
ctrs.setTourist_arrivals(a);
int r = 0;
cout << "Tourism ranking: ";
if (!(cin >> r)) {
cin.clear();
cin.ignore(1000, '\n');
}
ctrs.setTourism_ranking(r);
}
void get_city(city& cty)
{
string s;
cout << "City name: ";
cin >> s;
cty.setName(s);
cout << "Is a capital (y/n)? ";
cin >> s;
cty.setIscapital(s[0] == 'y');
int a = 0;
cout << "Number of Tourist arrivals: ";
if (!(cin >> a)) {
cin.clear();
cin.ignore(1000, '\n');
}
cty.setTourist_arrivals(a);
cout << "Travel by air (y/n)? ";
cin >> s;
cty.setTravel_by_air(s[0] == 'y');
}
int menu()
{
int o = 9999;
do {
cout << endl;
cout << "1. Add a country" << endl;
cout << "2. Add a city" << endl;
cout << "3. Remove a city" << endl;
cout << "4. Remove a country" << endl;
cout << "5. Display countries/cities" << endl;
cout << "0. Exit" << endl;
cout << "Option: ";
if (!(cin >> o)) {
cin.clear();
cin.ignore(1000, '\n');
}
} while ((o < 0 || o > 5) && (cout << "Invalid option" << endl));
return o;
}
int main()
{
dll<country> countries;
country co;
city cty;
string nam;
auto fc = [&](const string& nam)
{
for (auto i = countries.begin(); i != countries.end(); ++i)
if (i->data.getName() == nam)
return i;
return countries.end();
};
for (int o; (o = menu()) > 0;)
switch (o) {
case 1:
// Add a country
get_country(co);
countries.insertTail(co);
break;
case 2:
// Add a city
cout << "Enter country name: ";
cin >> nam;
if (auto c = fc(nam); c != countries.end()) {
get_city(cty);
c->data.add_city(cty);
} else
cout << "Country not found" << endl;
break;
case 3:
// Remove a city
cout << "Enter country name: ";
cin >> nam;
if (auto c = fc(nam); c != countries.end()) {
cout << "Enter city name: ";
cin >> nam;
if (!c->data.remove_city(nam))
cout << "City not found" << endl;
} else
cout << "Country not found" << endl;
break;
case 4:
// Remove a country
cout << "Enter country name: ";
cin >> nam;
if (auto c = fc(nam); c != countries.end())
countries.remove(c);
else
cout << "Country not found" << endl;
break;
case 5:
// Display countries and cities
for (const auto& c : countries) {
cout << "*" << c.getName() << endl;
c.display_cities();
}
break;
default:
cout << "Bad option" << endl;
}
}
Again, this hasn't been extensively tested so if any issues are found please post a message.
Of course, in practice standard STL containers would be used - rather than writing your own container and using that. Writing your own code for an existing stl container is only a nice exercise to develop coding skills and not something that would normally be done - except for the c++ gods that create the STL.
Note this is c++17 code and has been tested with VS2017 (15.5.4).
Last edited by 2kaud; 01-18-2018 at 06:54 AM.
-
Using STL map, one simple implementation could be
Code:
#include <iostream>
#include <string>
#include <map>
using namespace std;
class city {
public:
city() {}
city(const city& c) = default;
city(city&& c) = default;
city& operator=(const city& c) = default;
city& operator=(city&& c) = default;
string getName() const
{
return name;
}
void setName(const string& nam)
{
name = nam;
}
bool getIscapital() const
{
return iscapital;
}
void setIscapital(bool iscap)
{
iscapital = iscap;
}
unsigned int getTourist_arrivals() const
{
return tourist_arrivals;
}
void setTourist_arrivals(unsigned int arrivals)
{
tourist_arrivals = arrivals;
}
bool getTravel_by_air() const
{
return travel_by_air;
}
void setTravel_by_air(bool by_air)
{
travel_by_air = by_air;
}
private:
string name;
bool iscapital = false;
unsigned int tourist_arrivals = 0;
bool travel_by_air = false;
};
class country {
public:
country() {}
country(const country& c) = default;
country(country&& c) = default;
country& operator=(const country& c) = default;
country& operator=(country&& c) = default;
string getName() const
{
return name;
}
void setName(const string& nam)
{
name = nam;
}
string getRegion() const
{
return region;
}
void setRegion(const string& reg)
{
region = reg;
}
string getEconomy() const
{
return economy;
}
void setEconomy(const string& econ)
{
economy = econ;
}
unsigned int getTourist_arrivals() const
{
return tourist_arrivals;
}
void setTourist_arrivals(unsigned int arrivals)
{
tourist_arrivals = arrivals;
}
int getTourism_ranking() const
{
return tourism_ranking;
}
void setTourism_ranking(int ranking)
{
tourism_ranking = ranking;
}
bool add_city(const city& cty)
{
if (string nam; !cities.count(nam = cty.getName())) {
cities[nam] = cty;
return true;
}
return false;
}
void display_cities() const
{
for (const auto& c : cities)
cout << c.first << endl;
cout << endl;
}
bool city_exists(const string& nam) const
{
return cities.count(nam) > 0;
}
bool remove_city(const string& nam)
{
return cities.erase(nam) > 0;
}
private:
string name;
string region;
string economy;
unsigned int tourist_arrivals = 0;
int tourism_ranking = 0;
map<string, city> cities;
};
void get_country(country& ctrs, const string& nam = ""s)
{
string s;
if (nam.empty()) {
cout << "Country name: ";
cin >> s;
ctrs.setName(s);
} else
ctrs.setName(nam);
cout << "Region: ";
cin >> s;
ctrs.setRegion(s);
cout << "Economy: ";
cin >> s;
ctrs.setEconomy(s);
int a = 0;
cout << "Number of tourist arrivals: ";
if (!(cin >> a)) {
cin.clear();
cin.ignore(1000, '\n');
}
ctrs.setTourist_arrivals(a);
int r = 0;
cout << "Tourism ranking: ";
if (!(cin >> r)) {
cin.clear();
cin.ignore(1000, '\n');
}
ctrs.setTourism_ranking(r);
}
void get_city(city& cty, const string& nam = ""s)
{
string s;
if (nam.empty()) {
cout << "City name: ";
cin >> s;
cty.setName(s);
} else
cty.setName(nam);
cout << "Is a capital (y/n)? ";
cin >> s;
cty.setIscapital(s[0] == 'y');
int a = 0;
cout << "Number of Tourist arrivals: ";
if (!(cin >> a)) {
cin.clear();
cin.ignore(1000, '\n');
}
cty.setTourist_arrivals(a);
cout << "Travel by air (y/n)? ";
cin >> s;
cty.setTravel_by_air(s[0] == 'y');
}
int menu()
{
int o = 9999;
do {
cout << endl;
cout << "1. Add a country" << endl;
cout << "2. Add a city" << endl;
cout << "3. Remove a city" << endl;
cout << "4. Remove a country" << endl;
cout << "5. Display countries/cities" << endl;
cout << "0. Exit" << endl;
cout << "Option: ";
if (!(cin >> o)) {
cin.clear();
cin.ignore(1000, '\n');
}
} while ((o < 0 || o > 5) && (cout << "Invalid option" << endl));
return o;
}
int main()
{
map<string, country> countries;
country co;
city cty;
for (int o; (o = menu()) > 0;)
switch (string nam; o) {
case 1:
// Add a country
cout << "Country name: ";
cin >> nam;
if (!countries.count(nam)) {
get_country(co, nam);
countries[nam] = co;
} else
cout << "Country already exists" << endl;
break;
case 2:
// Add a city
cout << "Enter country name: ";
cin >> nam;
if (auto c = countries.find(nam); c != countries.end()) {
string cn;
cout << "City name: ";
cin >> cn;
if (!c->second.city_exists(cn)) {
get_city(cty, cn);
if (!c->second.add_city(cty))
cout << "Problem adding city" << endl;
} else
cout << "City already exists" << endl;
} else
cout << "Country not found" << endl;
break;
case 3:
// Remove a city
cout << "Enter country name: ";
cin >> nam;
if (auto c = countries.find(nam); c != countries.end()) {
cout << "Enter city name: ";
cin >> nam;
if (!c->second.remove_city(nam))
cout << "City not found" << endl;
} else
cout << "Country not found" << endl;
break;
case 4:
// Remove a country
cout << "Enter country name: ";
cin >> nam;
if (auto c = countries.find(nam); c != countries.end())
countries.erase(c);
else
cout << "Country not found" << endl;
break;
case 5:
// Display countries and cities
for (const auto& c : countries) {
cout << "*" << c.second.getName() << endl;
c.second.display_cities();
}
break;
default:
cout << "Bad option" << endl;
}
}
[Note VS2017 c++17 code]
This is more like what I would be expecting c++ 101 students to be able to code.
Last edited by 2kaud; 01-18-2018 at 07:00 AM.
Similar Threads
-
By noobie_coder in forum C++
Replies: 4
Last Post: 10-04-2008, 03:35 AM
-
Replies: 0
Last Post: 02-22-2002, 12:13 PM
-
Replies: 2
Last Post: 12-10-2001, 12:18 PM
-
Replies: 0
Last Post: 12-10-2001, 10:09 AM
-
Replies: 0
Last Post: 12-10-2001, 10:09 AM
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Development Centers
-- Android Development Center
-- Cloud Development Project Center
-- HTML5 Development Center
-- Windows Mobile Development Center
|