6.22 Lab: Doubly-Linked Lists (Park)
This commit is contained in:
parent
2f6299ac85
commit
274e3025b1
6
03-lists/.idea/vcs.xml
generated
Normal file
6
03-lists/.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
||||
</component>
|
||||
</project>
|
20
03-lists/national_parks.txt
Normal file
20
03-lists/national_parks.txt
Normal file
@ -0,0 +1,20 @@
|
||||
MOJ CA 1994 Mojave National Preserve; Spectacular Landscape in Absolute Solitude
|
||||
YOS CA 1890 Yosemite National Park; A Land of Giants
|
||||
LAS CA 1916 Lassen Volcanic National Park; Bubbling Below the Surface
|
||||
PRE CA 1962 Point Reyes National Seashore; Sky Above, Sea Beyond
|
||||
BRC UT 1928 Bryce Canyon National Park; Pillars of Stone
|
||||
DEV CA 1911 Devils Postpile National Monument; A Geologic Gem
|
||||
MUW CA 1908 Muir Woods National Monument; John Muir’s Cathedral
|
||||
CAL UT 1964 Canyonlands National Park; The Heart of the High Desert
|
||||
GLA MT 1910 Glacier National Park; Reflections of the Past
|
||||
ALC CA 1934 Alcatraz Island; Landmark Unlocked
|
||||
YEL WY 1872 Yellowstone National Park; Otherworldly on Earth
|
||||
ROC CO 1915 Rocky Mountain National Park; On Top of the World
|
||||
CRA OR 1902 Crater Lake National Park; Deep and Pristine Waters
|
||||
PIN CA 2013 Pinnacles National Park; Spectacular Remains of an Ancient Volcano
|
||||
DEN AK 1980 Denali National Park and Preserve; Beyond the Mountain
|
||||
ZIO UT 1919 Zion National Park; An Oasis Amidst the Desert
|
||||
JOS CA 1994 Joshua Tree National Park; The Outer Limits of Reality
|
||||
GRC AZ 1908 Grand Canyon National Park; A Sight Beyond Words
|
||||
ARC UT 1929 Arches National Park; Windows to the Sky
|
||||
DEA CA 1994 Death Valley National Park; A Land of Extremes
|
@ -4,4 +4,6 @@ project(04_dl_lists)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
||||
add_executable(04_dl_lists main.cpp
|
||||
StudentList.cpp)
|
||||
StudentList.cpp
|
||||
LinkedList.cpp
|
||||
Park.cpp)
|
||||
|
186
04-dl-lists/LinkedList.cpp
Normal file
186
04-dl-lists/LinkedList.cpp
Normal file
@ -0,0 +1,186 @@
|
||||
// Implementation file for the LinkedList class
|
||||
// Written By: Iurii Tatishchev
|
||||
// Reviewed & Modified by: Iurii Tatishchev
|
||||
// IDE: CLion
|
||||
|
||||
#include <iostream>
|
||||
#include "LinkedList.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// **************************************************
|
||||
// Constructor
|
||||
// This function allocates and initializes a sentinel node
|
||||
// A sentinel (or dummy) node is an extra node added before the first data record.
|
||||
// This convention simplifies and accelerates some list-manipulation algorithms,
|
||||
// by making sure that all links can be safely dereferenced and that every list
|
||||
// (even one that contains no data elements) always has a "first" node.
|
||||
// **************************************************
|
||||
LinkedList::LinkedList() {
|
||||
head = new ListNode; // head points to the sentinel node
|
||||
head->setNext(head);
|
||||
head->setPrev(head);
|
||||
length = 0;
|
||||
}
|
||||
|
||||
// **************************************************
|
||||
// The insertNode function inserts a new node in a
|
||||
// sorted linked list
|
||||
// **************************************************
|
||||
void LinkedList::insertNode(Park dataIn) {
|
||||
ListNode *newNode; // A new node
|
||||
ListNode *pCur; // To traverse the list
|
||||
ListNode *pPre; // The previous node
|
||||
|
||||
// Allocate a new node and store num there.
|
||||
newNode = new ListNode(dataIn);
|
||||
|
||||
// Initialize pointers
|
||||
pCur = head->getNext();
|
||||
|
||||
// Find location: skip all nodes whose code is less than dataIn's code
|
||||
while (pCur != head && newNode->getData().getCode() > pCur->getData().getCode()) {
|
||||
pCur = pCur->getNext();
|
||||
}
|
||||
|
||||
// Insert the new node between pPre and pCur
|
||||
pPre = pCur->getPrev();
|
||||
pPre->setNext(newNode);
|
||||
newNode->setNext(pCur);
|
||||
|
||||
pCur->setPrev(newNode);
|
||||
newNode->setPrev(pPre);
|
||||
|
||||
|
||||
// Update the counter
|
||||
length++;
|
||||
}
|
||||
|
||||
// **************************************************
|
||||
// The deleteNode function searches for a node
|
||||
// in a sorted linked list; if found, the node is
|
||||
// deleted from the list and from memory.
|
||||
// **************************************************
|
||||
bool LinkedList::deleteNode(string target) {
|
||||
ListNode *pCur; // To traverse the list
|
||||
ListNode *pPre; // To point to the previous node
|
||||
bool deleted = false;
|
||||
|
||||
// Initialize pointers
|
||||
pCur = head->getNext();
|
||||
|
||||
// Find node containing the target: Skip all nodes whose gpa is less than the target
|
||||
while (pCur != head && pCur->getData().getCode() < target) {
|
||||
pCur = pCur->getNext();
|
||||
}
|
||||
|
||||
// If found, delete the node
|
||||
if (pCur->getData().getCode() == target) {
|
||||
pPre = pCur->getPrev();
|
||||
pPre->setNext(pCur->getNext()); // Set next of prev
|
||||
pCur->getNext()->setPrev(pPre); // Set prev of next
|
||||
|
||||
delete pCur;
|
||||
deleted = true;
|
||||
length--;
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
|
||||
// **************************************************
|
||||
// displayListForw() shows the value
|
||||
// stored in each node of the linked list
|
||||
// pointed to by head, except the sentinel node,
|
||||
// from head to tail (ascending order).
|
||||
// **************************************************
|
||||
void LinkedList::displayListForw() const {
|
||||
ListNode *pCur; // To move through the list
|
||||
|
||||
// Position pCur: skip the head of the list.
|
||||
pCur = head->getNext();
|
||||
|
||||
// While pCur points to a node, traverse the list.
|
||||
while (pCur != head) {
|
||||
// Display the value in this node.
|
||||
pCur->getData().hDdisplay();
|
||||
|
||||
// Move to the next node.
|
||||
pCur = pCur->getNext();
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
// **************************************************
|
||||
// displayListBack() shows the value
|
||||
// stored in each node of the linked list
|
||||
// pointed to by head, except the sentinel node.
|
||||
// from tail to head (descending order).
|
||||
// **************************************************
|
||||
void LinkedList::displayListBack() const {
|
||||
ListNode *pCur; // To move through the list
|
||||
|
||||
// Position pCur: skip the head of the list.
|
||||
pCur = head->getPrev();
|
||||
|
||||
// While pCur points to a node, traverse the list.
|
||||
while (pCur != head) {
|
||||
// Display the value in this node.
|
||||
pCur->getData().hDdisplay();
|
||||
|
||||
// Move to the next node.
|
||||
pCur = pCur->getPrev();
|
||||
}
|
||||
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
|
||||
// **************************************************
|
||||
// The searchList function looks for a target college
|
||||
// in the sorted linked list: if found, returns true
|
||||
// and copies the data in that node to the output parameter
|
||||
// **************************************************
|
||||
bool LinkedList::searchList(const string& target, Park &dataOut) const {
|
||||
bool found = false; // assume target not found
|
||||
ListNode *pCur; // To move through the list
|
||||
|
||||
// Position pCur: skip the head of the list.
|
||||
pCur = head->getNext();
|
||||
// Find location: skip all nodes whose code is less than target
|
||||
while (pCur != head && pCur->getData().getCode() < target) {
|
||||
pCur = pCur->getNext();
|
||||
}
|
||||
|
||||
// If found, copy data to the output parameter, and change the flag to true
|
||||
if (pCur != head && pCur->getData().getCode() == target) {
|
||||
dataOut = pCur->getData();
|
||||
found = true;
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
// **************************************************
|
||||
// Destructor
|
||||
// This function deletes every node in the list.
|
||||
// **************************************************
|
||||
LinkedList::~LinkedList() {
|
||||
ListNode *pCur; // To traverse the list
|
||||
ListNode *pNext; // To hold the address of the next node
|
||||
|
||||
// Position nodePtr: skip the head of the list
|
||||
pCur = head->getNext();
|
||||
// While pCur is not at the end of the list...
|
||||
while (pCur != head) {
|
||||
// Save a pointer to the next node.
|
||||
pNext = pCur->getNext();
|
||||
|
||||
// Delete the current node.
|
||||
delete pCur;
|
||||
|
||||
// Position pCur at the next node.
|
||||
pCur = pNext;
|
||||
}
|
||||
|
||||
delete head; // delete the sentinel node
|
||||
}
|
37
04-dl-lists/LinkedList.h
Normal file
37
04-dl-lists/LinkedList.h
Normal file
@ -0,0 +1,37 @@
|
||||
// Specification file for the LinkedList class
|
||||
// Written By: Iurii Tatishchev
|
||||
// Reviewed by: Iurii Tatishchev
|
||||
// IDE: CLion
|
||||
|
||||
#ifndef LINKED_LIST_H
|
||||
#define LINKED_LIST_H
|
||||
|
||||
#include "ListNode.h"
|
||||
|
||||
class LinkedList {
|
||||
private:
|
||||
ListNode *head;
|
||||
int length;
|
||||
|
||||
public:
|
||||
LinkedList(); // constructor
|
||||
~LinkedList(); // destructor
|
||||
|
||||
// Linked list operations
|
||||
int getLength() const { return length; }
|
||||
|
||||
bool isEmpty() const { return length == 0; }
|
||||
|
||||
void insertNode(Park);
|
||||
|
||||
bool deleteNode(string);
|
||||
|
||||
void displayListForw() const;
|
||||
|
||||
void displayListBack() const;
|
||||
|
||||
bool searchList(const string &, Park &) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
43
04-dl-lists/ListNode.h
Normal file
43
04-dl-lists/ListNode.h
Normal file
@ -0,0 +1,43 @@
|
||||
// Specification file for the ListNode class
|
||||
// Written By: Iurii Tatishchev
|
||||
// Reviewed & Modified by: Iurii Tatishchev
|
||||
// IDE: CLion
|
||||
|
||||
#ifndef LISTNODE_H
|
||||
#define LISTNODE_H
|
||||
|
||||
#include <iostream>
|
||||
#include "Park.h"
|
||||
|
||||
class ListNode {
|
||||
private:
|
||||
Park data; // store data
|
||||
ListNode *forw; // a pointer to the next node in the list
|
||||
ListNode *back; // a pointer to the previous node in the list
|
||||
public:
|
||||
// Constructor
|
||||
ListNode() { forw = back = nullptr; }
|
||||
|
||||
ListNode(const Park &dataIn, ListNode *forw = nullptr, ListNode *back = nullptr) {
|
||||
data = dataIn;
|
||||
this->forw = forw;
|
||||
this->back = back;
|
||||
}
|
||||
|
||||
// setters
|
||||
// set the forw pointer
|
||||
void setNext(ListNode *nextPtr) { forw = nextPtr; }
|
||||
// set the back pointer
|
||||
void setPrev(ListNode *prevPtr) { back = prevPtr; }
|
||||
|
||||
// getters
|
||||
// return pointer in the next node
|
||||
ListNode *getNext() const { return forw; }
|
||||
// return pointer in the previous node
|
||||
ListNode *getPrev() const { return back; }
|
||||
|
||||
// return data object in the listnode
|
||||
Park& getData() { return data; }
|
||||
};
|
||||
|
||||
#endif
|
60
04-dl-lists/Park.cpp
Normal file
60
04-dl-lists/Park.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
// Implementation file for the Park class
|
||||
// Written By: Iurii Tatishchev
|
||||
// Reviewed By: Iurii Tatishchev
|
||||
// IDE: CLion
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
|
||||
#include "Park.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// **************************************************
|
||||
// Constructor
|
||||
// **************************************************
|
||||
Park::Park() {
|
||||
code = "";
|
||||
state = "";
|
||||
name = "";
|
||||
description = "";
|
||||
year = -1;
|
||||
}
|
||||
|
||||
// **************************************************
|
||||
// Overloaded Constructor
|
||||
// **************************************************
|
||||
Park::Park(string cd, string st, string nm, string dsc, int yr) {
|
||||
code = cd;
|
||||
state = st;
|
||||
name = nm;
|
||||
description = dsc;
|
||||
year = yr;
|
||||
}
|
||||
|
||||
// ***********************************************************
|
||||
// Displays the values of a Park object member variables
|
||||
// on one line (horizontal display)
|
||||
// ***********************************************************
|
||||
void Park::hDdisplay() const {
|
||||
cout << code << " ";
|
||||
cout << state << " ";
|
||||
cout << year << " ";
|
||||
cout << name << " ";
|
||||
//cout << "(" << description << ")";
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
// ***********************************************************
|
||||
// Displays the values of a Park object member variables
|
||||
// one per line (vertical display)
|
||||
// ***********************************************************
|
||||
void Park::vDisplay() const {
|
||||
cout << name << endl;
|
||||
cout << description << endl;
|
||||
cout << state << endl;
|
||||
cout << year << endl;
|
||||
}
|
||||
|
64
04-dl-lists/Park.h
Normal file
64
04-dl-lists/Park.h
Normal file
@ -0,0 +1,64 @@
|
||||
// Specification file for the Park class
|
||||
// Written By: Iurii Tatishchev
|
||||
// Reviewed by: Iurii Tatishchev
|
||||
// IDE: CLion
|
||||
|
||||
#ifndef PARK_H
|
||||
#define PARK_H
|
||||
|
||||
// #include<iostream>
|
||||
#include<string>
|
||||
// #include<cstdlib>
|
||||
|
||||
// using namespace std;
|
||||
// ^^^^^ This statement
|
||||
// in a header file of a complex project could create
|
||||
// namespace management problems for the entire project
|
||||
// (such as name collisions).
|
||||
// Do not write using namespace at the top level in a header file!
|
||||
|
||||
using std::string;
|
||||
|
||||
class Park {
|
||||
private:
|
||||
string code; // the unique park identifier
|
||||
string state;
|
||||
string name;
|
||||
string description;
|
||||
int year;
|
||||
|
||||
public:
|
||||
// constructors
|
||||
Park();
|
||||
|
||||
Park(string, string, string, string, int);
|
||||
|
||||
// setters
|
||||
void setCode(string cd) { code = cd; }
|
||||
|
||||
void setState(string st) { state = st; }
|
||||
|
||||
void setName(string nm) { name = nm; }
|
||||
|
||||
void setDesc(int dsc) { description = dsc; }
|
||||
|
||||
void setYear(int yr) { year = yr; }
|
||||
|
||||
// getters
|
||||
string getCode() const { return code; }
|
||||
|
||||
string getState() const { return state; }
|
||||
|
||||
string getName() const { return name; }
|
||||
|
||||
string getDesc() const { return description; }
|
||||
|
||||
int getYear() const { return year; }
|
||||
|
||||
// other functions
|
||||
void hDdisplay() const;
|
||||
|
||||
void vDisplay() const;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,70 +1,147 @@
|
||||
/*
|
||||
CIS 22C: Sorted Circular Doubly-Linked List with Sentinel Node
|
||||
Sorted Circular Doubly-Linked List with Sentinel Node
|
||||
|
||||
This program:
|
||||
- Creates a sorted linked list (student name and gpa). The list is sorted in ascending order by name. Assume name is a unique identifier.
|
||||
- Displays the list forwards(A to Z)
|
||||
- Displays the list backwards(Z to A)
|
||||
Build and procees a sorted linked list of Park objects.
|
||||
The list is sorted in ascending order by the Park code, a unique identifier.
|
||||
|
||||
Your task is to finish writing the following three functions:
|
||||
- default constructor (reuse code from your previous lab)
|
||||
- `displayListBack()` (reuse code from your previous lab)
|
||||
- `insertNode()` - change this function to reject duplicates. Assume `name` is a unique key.
|
||||
|
||||
Written by: Iurii Tatishchev
|
||||
Reviewed by: Iurii Tatishchev
|
||||
IDE: CLion
|
||||
// Written by: Iurii Tatishchev
|
||||
// Reviewed & Modified by: Iurii Tatishchev
|
||||
// IDE: CLion
|
||||
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include "StudentList.h"
|
||||
#include <string>
|
||||
#include <cctype> // toupper()
|
||||
#include "LinkedList.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
void buildList(StudentList &);
|
||||
void buildList(const string &filename, LinkedList &list);
|
||||
|
||||
void deleteManager(LinkedList &list);
|
||||
|
||||
void searchManager(const LinkedList &list);
|
||||
|
||||
void displayManager(const LinkedList &list);
|
||||
|
||||
int main() {
|
||||
// Define a StudentList object
|
||||
StudentList list;
|
||||
string inputFileName = "national_parks.txt";
|
||||
LinkedList list;
|
||||
|
||||
buildList(list); // insert data into the list
|
||||
cout << "The number of elements in the list is " << list.getCount() << "." << endl;
|
||||
string answer;
|
||||
cout << "Insert [Y/N]? ";
|
||||
cin >> answer;
|
||||
if (answer == "Y" || answer == "y") {
|
||||
Student s;
|
||||
cout << "Enter gpa then enter name:" << endl;
|
||||
cin >> s.gpa >> s.name;
|
||||
if (!list.insertNode(s)) {
|
||||
cout << s.name << " - rejected: duplicate key!" << endl;
|
||||
}
|
||||
cout << "The number of elements in the list is " << list.getCount() << "." << endl;
|
||||
}
|
||||
cout << endl;
|
||||
list.displayListForw();
|
||||
list.displayListBack();
|
||||
buildList(inputFileName, list);
|
||||
displayManager(list);
|
||||
searchManager(list);
|
||||
deleteManager(list);
|
||||
displayManager(list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* **************************************************
|
||||
This function builds a sorted linked list with data from the keyboard.
|
||||
The list is sorted in ascending order by the students' names.
|
||||
It calls the insertNode() function that inserts the new data at the right location in the linked list.
|
||||
An input line contains the gpa of a student follow by its name (assume it is a single word name)
|
||||
To stop reading enter "#"
|
||||
************************************************** */
|
||||
void buildList(StudentList &list) {
|
||||
/*
|
||||
This function reads data about national parks from a file and inserts them
|
||||
into a sorted linked list. The list is sorted in ascending order by code.
|
||||
*/
|
||||
void buildList(const string &filename, LinkedList &list) {
|
||||
ifstream inputFile(filename);
|
||||
cout << "Reading data from \"" << filename << "\"" << endl;
|
||||
|
||||
if (!inputFile) {
|
||||
cout << "Error opening the input file: \"" << filename << "\"" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
string line;
|
||||
getline(cin, line);
|
||||
while (line != "#") {
|
||||
stringstream temp(line); // create a stringstream named temp with data from line
|
||||
Student newStu;
|
||||
temp >> newStu.gpa; // read gpa from temp
|
||||
temp >> newStu.name; // read name from temp
|
||||
list.insertNode(newStu);
|
||||
getline(cin, line);
|
||||
while (getline(inputFile, line)) {
|
||||
int year;
|
||||
string code, name, state, dsc;
|
||||
|
||||
stringstream temp(line); // create temp with data from line
|
||||
temp >> code; // read from temp
|
||||
temp >> state;
|
||||
temp >> year;
|
||||
temp.ignore(); // to ignore space in front of name
|
||||
getline(temp, name, ';'); // stop reading name at ';'
|
||||
temp.ignore(); // to ignore space in front of description
|
||||
getline(temp, dsc);
|
||||
// create a Park object and initialize it with data from file
|
||||
Park aPark(code, state, name, dsc, year);
|
||||
list.insertNode(aPark);
|
||||
}
|
||||
|
||||
inputFile.close();
|
||||
}
|
||||
|
||||
/*
|
||||
Delete manager: delete items from the list until the user enters Q to quit
|
||||
deleting
|
||||
Input Parameter: list
|
||||
*/
|
||||
void deleteManager(LinkedList &list) {
|
||||
string targetCode;
|
||||
|
||||
cout << endl << " Delete" << endl;
|
||||
cout << "=======" << endl;
|
||||
|
||||
while (targetCode != "Q") {
|
||||
cout << "Enter a park code (or Q to stop deleting):" << endl;
|
||||
getline(cin, targetCode);
|
||||
targetCode[0] = toupper(targetCode[0]);
|
||||
if (targetCode != "Q") {
|
||||
if (list.deleteNode(targetCode))
|
||||
cout << " " << targetCode << " has been deleted!" << endl;
|
||||
else
|
||||
cout << "Park \"" << targetCode << "\" was not found in this list." << endl;
|
||||
}
|
||||
}
|
||||
cout << "___________________END DELETE SECTION_____" << endl;
|
||||
}
|
||||
|
||||
/*
|
||||
Search manager: search the list until the user enters Q to quit searching
|
||||
Input Parameter: list
|
||||
*/
|
||||
void searchManager(const LinkedList &list) {
|
||||
string targetCode = "";
|
||||
Park aPark;
|
||||
|
||||
cout << endl << " Search" << endl;
|
||||
cout << "=======" << endl;
|
||||
|
||||
while (targetCode != "Q") {
|
||||
cout << "Enter a park code (or Q to stop searching):" << endl;
|
||||
getline(cin, targetCode);
|
||||
targetCode[0] = toupper(targetCode[0]);
|
||||
if (targetCode != "Q") {
|
||||
if (list.searchList(targetCode, aPark))
|
||||
aPark.vDisplay();
|
||||
else
|
||||
cout << "Park \"" << targetCode << "\" was not found in this list." << endl;
|
||||
}
|
||||
}
|
||||
cout << "___________________END SEARCH SECTION _____" << endl;
|
||||
}
|
||||
|
||||
/*
|
||||
Display manager:
|
||||
- displays the number of national parks in this list
|
||||
- calls the displayListForw()/displayListBack() function upon request
|
||||
Input Parameter: list
|
||||
*/
|
||||
void displayManager(const LinkedList &list) {
|
||||
string action;
|
||||
|
||||
cout << "Number of National Parks in this list: " << list.getLength() << endl;
|
||||
cout << "Display list [F/B/N]?" << endl;
|
||||
getline(cin, action);
|
||||
|
||||
switch (toupper(action[0])) {
|
||||
case 'F':
|
||||
list.displayListForw();
|
||||
break;
|
||||
case 'B':
|
||||
list.displayListBack();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
20
04-dl-lists/national_parks.txt
Normal file
20
04-dl-lists/national_parks.txt
Normal file
@ -0,0 +1,20 @@
|
||||
MOJ CA 1994 Mojave National Preserve; Spectacular Landscape in Absolute Solitude
|
||||
YOS CA 1890 Yosemite National Park; A Land of Giants
|
||||
LAS CA 1916 Lassen Volcanic National Park; Bubbling Below the Surface
|
||||
PRE CA 1962 Point Reyes National Seashore; Sky Above, Sea Beyond
|
||||
BRC UT 1928 Bryce Canyon National Park; Pillars of Stone
|
||||
DEV CA 1911 Devils Postpile National Monument; A Geologic Gem
|
||||
MUW CA 1908 Muir Woods National Monument; John Muir’s Cathedral
|
||||
CAL UT 1964 Canyonlands National Park; The Heart of the High Desert
|
||||
GLA MT 1910 Glacier National Park; Reflections of the Past
|
||||
ALC CA 1934 Alcatraz Island; Landmark Unlocked
|
||||
YEL WY 1872 Yellowstone National Park; Otherworldly on Earth
|
||||
ROC CO 1915 Rocky Mountain National Park; On Top of the World
|
||||
CRA OR 1902 Crater Lake National Park; Deep and Pristine Waters
|
||||
PIN CA 2013 Pinnacles National Park; Spectacular Remains of an Ancient Volcano
|
||||
DEN AK 1980 Denali National Park and Preserve; Beyond the Mountain
|
||||
ZIO UT 1919 Zion National Park; An Oasis Amidst the Desert
|
||||
JOS CA 1994 Joshua Tree National Park; The Outer Limits of Reality
|
||||
GRC AZ 1908 Grand Canyon National Park; A Sight Beyond Words
|
||||
ARC UT 1929 Arches National Park; Windows to the Sky
|
||||
DEA CA 1994 Death Valley National Park; A Land of Extremes
|
Loading…
x
Reference in New Issue
Block a user