DragonOsman

linked_lists.cpp

Oct 27th, 2017
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.03 KB | None | 0 0
  1. // Osman Zakir
  2. // 9 / 7 / 2017
  3. // Bjarne Stroustrup: Programming: Principles and Practice Using C++ 2nd Edition
  4. // Chapter 17 Exercises 11-13
  5.  
  6. #include <iostream>
  7. #include <stdexcept>
  8. #include <vld.h>
  9. #include "../../cust_std_lib_facilities.h"
  10.  
  11. struct God
  12.     {
  13.         God(const std::string &name, const std::string &myth, const std::string &vehicle, const std::string &weapon)
  14.             : m_name{ name }, m_myth{ myth }, m_vehicle{ vehicle }, m_weapon{ weapon } { }
  15.         God()
  16.             : m_name{}, m_myth{}, m_vehicle{}, m_weapon{} {}
  17.  
  18.         std::string m_name;
  19.         std::string m_myth;
  20.         std::string m_vehicle;
  21.         std::string m_weapon;
  22.     };
  23.  
  24. class Link
  25. {
  26. public:
  27.     Link(const God &god, Link *p = nullptr, Link *n = nullptr)
  28.         : m_god{ god }, m_prev{ p }, m_succ{ n }
  29.     {  
  30.     }
  31.  
  32.     Link *insert(Link *n);                                            // insert n before this object
  33.     Link *add(Link *n);                                               // insert n after this object
  34.     Link *erase();                                                    // remove this object from list
  35.     Link *find(const std::string &name);                              // find node matching passed in name in list
  36.     Link *find_if_myth(const std::string &myth);                      // find node matching passed in myth in list
  37.     const Link *find_if_myth(const std::string &myth) const;          // find node matching passed in myth in const list
  38.     const Link *find(const std::string &name) const;                  // find node matching passed in name in const list
  39.     Link *advance(int n) const;                                       // advance n positions in list
  40.     Link *add_ordered(Link *n);                                       // insert n in its correct lexicographical position
  41.  
  42.     God god() const { return m_god; }
  43.     Link *next() const { return m_succ; }
  44.     Link *previous() const { return m_prev; }
  45. private:
  46.     God m_god;
  47.     Link *m_prev;
  48.     Link *m_succ;
  49. };
  50.  
  51. void print_all(Link *p);
  52. void move_nodes(Link *dest_list, Link *source_list, const std::string &myth);
  53.  
  54. int main()
  55. {
  56.     try
  57.     {
  58.         Link *gods = new Link{ { "Odin", "Norse", "Eight-legged flying horse called Sleipnir", "Spear called Gungnir" } };
  59.         gods = gods->add_ordered(new Link{ { "Thor", "Norse", "Chariot pulled by goats Tanngrisnir and Tanngnjostr",
  60.             "Hammer called Mjolnir" } });
  61.         gods = gods->add_ordered(new Link{ { "Baldr", "Norse", "A giant ship called Hringorni", "None" } });
  62.         gods = gods->add_ordered(new Link{ { "Frejya", "Norse", "Chariot pulled by two cats", "Magic called seidr" } });
  63.         gods = gods->add_ordered(new Link{ { "Zeus", "Greek", "A chariot pulled by the four major winds shaped as horses",
  64.             "Thunderbolt and the shield called Aegis" } });
  65.         gods = gods->add_ordered(new Link{ { "Hera", "Greek", "A chariot drawn by peacocks", "Her intelligence" } });
  66.         gods = gods->add_ordered(new Link{ { "Athena", "Greek", "", "Allowed to use Zeus's Thunderbolt and the Aegis" } });
  67.         gods = gods->add_ordered(new Link{ { "Ares", "Greek", "War chariot", "Sword and spear" } });
  68.         gods = gods->add_ordered(new Link{ { "Amaterasu", "Japanese", "", "Sword of Kusanagi, Jewel of Yasakani, Mirror of Yata" } });
  69.         gods = gods->add_ordered(new Link{ { "Susanoo", "Japanese", "", "Sword of Totsuka" } });
  70.         gods = gods->add_ordered(new Link{ { "Izanagi", "Japanese", "", "Sword of Totsuka (later given to Susanoo)" } });
  71.         gods = gods->add_ordered(new Link{ { "Bishamonten", "Japanese", "", "A spear" } });
  72.  
  73.         Link *Odin = new Link{ { "Odin", "Norse", "Eight-legged flying horse called Sleipnir", "Spear called Gungnir" } };
  74.         Link *Zeus = new Link{ { "Zeus", "Greek", "A chariot pulled by the four major winds shaped as horses",
  75.             "Thunderbolt and the shield called Aegis" } };
  76.         Link *Amaterasu = new Link{ { "Amaterasu", "Japanese", "", "Sword of Kusanagi, Jewel of Yasakani, Mirror of Yata" } };
  77.  
  78.         Link *norse_gods = Odin;
  79.         Link *greek_gods = Zeus;
  80.         Link *jap_gods = Amaterasu;
  81.  
  82.         while (gods->next() && gods->find_if_myth("Norse"))
  83.         {
  84.             move_nodes(norse_gods, gods, "Norse");
  85.         }
  86.         while (gods->next() && gods->find_if_myth("Greek"))
  87.         {
  88.             move_nodes(greek_gods, gods, "Greek");
  89.         }
  90.         while (gods->next() && gods->find_if_myth("Japanese"))
  91.         {
  92.             move_nodes(jap_gods, gods, "Japanese");
  93.         }
  94.  
  95.         std::cout << "\nnorse_gods list:\n";
  96.         print_all(norse_gods);
  97.         std::cout << "\ngreek_gods list:\n";
  98.         print_all(greek_gods);
  99.         std::cout << "\njap_gods list:\n";
  100.         print_all(jap_gods);
  101.         std::cout << "\ngods list:\n";
  102.         print_all(gods);
  103.  
  104.         delete Odin;
  105.         delete Zeus;
  106.         delete Amaterasu;
  107.         delete gods;
  108.     }
  109.     catch (const std::runtime_error &rte)
  110.     {
  111.         std::cerr << "Runtime error: " << rte.what() << '\n';
  112.         keep_window_open();
  113.         return 1;
  114.     }
  115.     catch (const std::bad_alloc &ba)
  116.     {
  117.         std::cerr << "Bad allocation error: " << ba.what() << '\n';
  118.         keep_window_open();
  119.         return 2;
  120.     }
  121.     catch (const std::exception &e)
  122.     {
  123.         std::cerr << "Exception: " << e.what() << "\n";
  124.         keep_window_open();
  125.         return 3;
  126.     }
  127.     catch (...)
  128.     {
  129.         std::cerr << "An unknown exception occurred\n";
  130.         keep_window_open();
  131.         return 4;
  132.     }
  133.  
  134.     keep_window_open();
  135. }
  136.  
  137. Link *Link::insert(Link *n)
  138. {
  139.     if (n == nullptr)
  140.     {
  141.         return this;
  142.     }
  143.     if (this == nullptr)
  144.     {
  145.         return n;
  146.     }
  147.     n->m_succ = this;    // this object comes after n
  148.     if (m_prev)
  149.     {
  150.         m_prev->m_succ = n;
  151.     }
  152.     n->m_prev = m_prev;
  153.     m_prev = n;
  154.     return n;
  155. }
  156.  
  157. Link *Link::add(Link *n)
  158. {
  159.     if (n == nullptr)
  160.     {
  161.         return this;
  162.     }
  163.     if (this == nullptr)
  164.     {
  165.         return n;
  166.     }
  167.     n->m_prev = this;
  168.     if (m_succ)
  169.     {
  170.         m_succ->m_prev = n;
  171.     }
  172.     n->m_succ = m_succ;
  173.     m_succ = n;
  174.     return n;
  175. }
  176.  
  177. Link *Link::erase()
  178. {
  179.     Link *trav = this;
  180.     if (trav == nullptr)
  181.     {
  182.         return this;
  183.     }
  184.     if (trav->m_succ)
  185.     {
  186.         trav->m_succ->m_prev = trav->m_prev;
  187.     }
  188.     if (trav->m_prev)
  189.     {
  190.         trav->m_prev->m_succ = trav->m_succ;
  191.     }
  192.     return trav->m_succ;
  193. }
  194.  
  195. Link *Link::find(const std::string &name)
  196. {
  197.     Link *trav = this;
  198.     while (trav != nullptr)
  199.     {
  200.         if (trav->m_god.m_name == name)
  201.         {
  202.             return trav;
  203.         }
  204.         trav = trav->m_succ;
  205.     }
  206.     return nullptr;
  207. }
  208.  
  209. Link *Link::find_if_myth(const std::string &myth)
  210. {
  211.     Link *trav = this;
  212.     if (trav->m_prev)
  213.     {
  214.         while (trav->m_prev)
  215.         {
  216.             trav = trav->m_prev;
  217.         }
  218.     }
  219.  
  220.     while (trav && trav->m_succ)
  221.     {
  222.         if (trav->m_god.m_myth == myth)
  223.         {
  224.             return trav;
  225.         }
  226.         trav = trav->m_succ;
  227.     }
  228.     return nullptr;
  229. }
  230.  
  231. const Link *Link::find_if_myth(const std::string &myth) const
  232. {
  233.     const Link *c_trav = this;                    // const pointer
  234.     Link *nc_trav = const_cast<Link*>(c_trav);    // non-const pointer
  235.     while (c_trav != nullptr && nc_trav != nullptr)
  236.     {
  237.         if (c_trav->m_god.m_myth == myth)
  238.         {
  239.             return c_trav;
  240.         }
  241.         nc_trav = nc_trav->m_succ;
  242.     }
  243.     return nullptr;
  244. }
  245.  
  246. const Link *Link::find(const std::string &name) const
  247. {
  248.     const Link *c_trav = this;                    // const pointer
  249.     Link *nc_trav = const_cast<Link*>(c_trav);    // non-const pointer
  250.     while (c_trav != nullptr && nc_trav != nullptr)
  251.     {
  252.         if (c_trav->m_god.m_name == name)
  253.         {
  254.             return c_trav;
  255.         }
  256.         nc_trav = nc_trav->m_succ;
  257.     }
  258.     return nullptr;
  259. }
  260.  
  261. Link *Link::advance(int n) const
  262. {
  263.     Link *trav = const_cast<Link *>(this);
  264.     if (trav == nullptr)
  265.     {
  266.         return const_cast<Link*>(this);
  267.     }
  268.     if (n > 0)
  269.     {
  270.         while (n--)
  271.         {
  272.             if (trav->m_succ == nullptr)
  273.             {
  274.                 return const_cast<Link*>(this);
  275.             }
  276.             trav = trav->m_succ;
  277.         }
  278.     }
  279.     else if (n < 0)
  280.     {
  281.         while (n++)
  282.         {
  283.             if (trav->m_prev == nullptr)
  284.             {
  285.                 return const_cast<Link*>(this);
  286.             }
  287.             trav = trav->m_prev;
  288.         }
  289.     }
  290.     return trav;
  291. }
  292.  
  293. Link *Link::add_ordered(Link *n)
  294. {
  295.     if (n == nullptr)
  296.     {
  297.         return this;
  298.     }
  299.     if (this == nullptr)
  300.     {
  301.         return n;
  302.     }
  303.    
  304.     Link *trav = this;
  305.     if (!trav)
  306.     {
  307.         return n;
  308.     }
  309.  
  310.     // to make sure to start at head of the list
  311.     while (trav->m_prev != nullptr)
  312.     {
  313.         trav = trav->m_prev;
  314.     }
  315.  
  316.     while (trav->m_god.m_name < n->m_god.m_name && trav->m_succ)
  317.     {
  318.         trav = trav->m_succ;
  319.     }
  320.  
  321.     if (n->m_god.m_name < trav->m_god.m_name)
  322.     {
  323.         trav = trav->insert(n);
  324.     }
  325.     else if (!(n->m_god.m_name < trav->m_god.m_name))
  326.     {
  327.         trav = trav->add(n);
  328.     }
  329.     return trav;
  330. }
  331.  
  332. void move_nodes(Link *dest_list, Link *source_list, const std::string &myth)
  333. {
  334.     Link *trav = source_list->find_if_myth(myth);
  335.     if (trav)
  336.     {
  337.         if (trav == source_list)
  338.         {
  339.             trav = source_list->next();
  340.         }
  341.         trav->erase();
  342.         if (trav->god().m_name != dest_list->god().m_name && trav->god().m_myth == myth)
  343.         {
  344.             dest_list = dest_list->add_ordered(trav);
  345.         }
  346.     }
  347. }
  348.  
  349. void print_all(Link *p)
  350. {
  351.     while (p->previous() != nullptr && p != nullptr)
  352.     {
  353.         p = p->previous();
  354.     }
  355.  
  356.     std::cout << "{\n";
  357.     while (p)
  358.     {
  359.         std::cout << "Name: " << p->god().m_name
  360.             << "; Myth: " << p->god().m_myth;
  361.         if (p->god().m_vehicle != "")
  362.         {
  363.             std::cout << "; Vehicle: " << p->god().m_vehicle;
  364.         }
  365.         else
  366.         {
  367.             std::cout << "; Vehicle: N/A";
  368.         }
  369.         if (p->god().m_weapon != "")
  370.         {
  371.             std::cout << "; Weapon: " << p->god().m_weapon;
  372.         }
  373.         else
  374.         {
  375.             std::cout << "; Weapon: N/A";
  376.         }
  377.         if ((p = p->next()))
  378.         {
  379.             std::cout << "\n";
  380.         }
  381.     }
  382.     std::cout << "\n}\n";
  383. }
Add Comment
Please, Sign In to add comment