Kendall Smallcse.csusb.edu/tongyu/studentwork/cs330/hw/hw3_dir/Small... · 2016. 11. 2. · Kendall...

Preview:

Citation preview

Kendall Small

Professor Yu

CSE 330

Homework 3

I believe I deserve full credit (55 points) for this assignment because I successfully completed

each problem and included output.

1.( 20 points ) Suppose for a certain application it was important to always know the number of

elements in a list. The implementation of the member function size() of class List discussed in

class and presented in the textbook employs a loop, and thus has O(n) execution time.

Using inheritance, write a new template class named countedList that maintains an explicit

count on the number of values held in the list, and the function size() will return this count. You

need to rewrite the insertion and deletion functions in the subclass so that the count is handled

appropriately.

//list.h

#ifndef LIST_H

#define LIST_H

template <typename T> class countedList;

template <typename T> class Node; //forward declaration

template <typename T> class listIterator; //forward declaration

template<typename T>

class List {

protected:

Node<T> *first;

Node<T> *last;

public:

//type definition

typedef T value_type;

typedef listIterator<T> iterator;

//constructor and destructor

List ();

virtual ~List();

//operations

bool empty();

int size();

T &front(); //returns first element

T &back(); //returns last element

void push_front ( T & ); //insert from the front

void push_back( T & ); //insert from the back

void pop_front(); //remove first element

void pop_back(); //remove last element

iterator begin();

iterator end();

void sort();

void insert( iterator &, T &);

void erase( iterator & );

void erase( iterator &, iterator &);

};

template <typename T>

class listIterator {

typedef listIterator<T> iterator;

protected:

List<T> *theList;

Node<T> *currentNode;

friend class List<T>;

friend class countedList<T>;

public:

//constructor

listIterator ();

listIterator ( List<T> *tl, Node<T> *cl );

T &operator * (); //dereferencing

bool operator != ( iterator &rhs );

iterator & operator ++ ( int ); //prefix

iterator operator ++ (); //postfix

};

#endif

//Node.h

#ifndef NODE_H

#define NODE_H

template <typename T> class countedList;

template <typename T> class List; //forward declaration

template <typename T> class listIterator; //forward declaration

//a Node is a node ( cell )

template <typename T> class Node {

private:

Node ( T &v ); //constructor

T value;

Node<T> *next;

Node<T> *prev;

//allow lists and iterators to access members

friend class List<T>;

friend class listIterator<T>;

friend class countedList<T>;

};

#endif

//list.cpp

#include <iostream>

#include "list.h"

#include "Node.h"

#include <stdio.h>

template<typename T>

List<T>::List()

{

first = last = 0; //null list

}

template<typename T>

bool List<T>::empty()

{

return first == 0;

}

template<typename T>

int List<T>::size()

//count the number of elements in collection

/*

Comments from Tong: This is NOT a good implementation as

it takes time to traverse the list. A better way is to include

a field called 'size' in the List class; when elements are

inserted or deleted, size is adjusted.

*/

{

int count = 0;

Node<T> *p;

for ( p = first; p != 0; p = p->next )

count++;

return count;

}

template<typename T>

void List<T>::push_front( T &a )

{

Node<T> *newNode = new Node<T> ( a );

if ( empty() )

first = last = newNode;

else {

first->prev = newNode;

newNode->next = first;

first = newNode;

}

}

template<typename T>

void List<T>::pop_front()

{

Node <T> *temp = first;

first = first->next;

if ( first != 0 )

first->prev = 0;

else

last = 0;

delete temp;

}

template<typename T>

List<T>::~List()

{

Node <T> *p = first;

while ( p != 0 ) {

Node<T> *temp = p;

p = p->next;

delete temp;

}

}

template<typename T>

listIterator<T> List<T>::begin()

{

return iterator ( this, first );

}

template<typename T>

listIterator<T> List<T>::end()

{

return iterator ( this, 0 ); //points beyond last

}

//listIterator

//constructors

template<typename T>

listIterator<T>::listIterator()

{

}

template<typename T>

listIterator<T>::listIterator( List<T> *lp, Node<T> *lkp )

{

theList = lp;

currentNode = lkp;

}

template<typename T>

T & listIterator<T>::operator * ()

{

return currentNode->value;

}

template<typename T>

bool listIterator<T>::operator != ( iterator &rhs )

{

return currentNode != rhs.currentNode;

}

template<typename T>

listIterator<T> & listIterator<T>::operator ++ (int)

{

currentNode = currentNode->next;

return *this;

}

template<typename T>

listIterator<T> listIterator<T>::operator ++ ()

//postfix form of increment ( e.g. assigned, then increment )

{

//make an old copy

listIterator<T> clone ( theList, currentNode );

currentNode = currentNode->next; //advance pointer

return clone; //return old iterator

}

template<typename T>

void List<T>::insert( listIterator<T> &itr, T &a )

{

Node<T> *p = new Node<T> ( a );

Node<T> *current = itr.currentNode;

if ( empty() ) { //empty list

first = last = p;

return;

}

//assert ( current );

if ( current == 0 ){ //point to end, thus append to list

last->next = p;

p->next = 0;

p->prev = last;

last = p;

return;

}

//otherwise, always insert before

p->next = current;

p->prev = current->prev;

current->prev = p;

current = p->prev;

if ( current != 0 )

current->next = p;

else

first = p;

}

template<typename T>

void List<T>::erase ( listIterator<T> &start, listIterator<T> &stop )

//remove elements from the range ( before stop )

{

//List is friend of listIterator, so it can access listIterator's

// private or protected data member

Node<T> *p = start.currentNode;

Node<T> *q = p->prev;

Node<T> *stopNode = stop.currentNode;

if ( q == 0 ) { //removing initial portion of list

first = stopNode;

if ( stopNode == 0 ) //pointing to end

last = 0; //whole list is deleted

else

stopNode->prev = 0;

} else {

q->next = stopNode;

if ( stopNode == 0 )

last = q;

else

stopNode->prev = q; // q->prev = q;

}

//now delete the atoms

while ( start != stop ) {

listIterator<T> next = start;

++next;

delete start.currentNode;

start = next;

}

}

//Node.cpp

#include "Node.h"

#include "list.h"

template <typename T>

Node<T>::Node( T &v )

{

value = v;

prev = next = 0;

}

//countedList

//Kendall Small

#include "list.h"

#ifndef COUNTEDLIST_H

#define COUNTEDLIST_H

template<typename T>

class countedList : public List<T>{

protected:

int size;

public:

countedList(){size=0;}

void c_erase(listIterator<T> &start, listIterator<T> &stop);

void c_insert(listIterator<T> &itr, T &a);

void c_pop_front();

void c_push_front(T &a);

int c_size(){return size;}

~countedList();

};

#endif

//countedList.cpp

//Kendall Small

//#include "list.h"

#include "countedlist.h"

#include<iostream>

//using namespace std;

template<typename T>

countedList<T>::~countedList()

{

Node <T> *p = List<T>::first;

while ( p != 0 ) {

Node<T> *temp = p;

p = p->next;

delete temp;

}

}

template<typename T>

void countedList<T>::c_push_front(T &a)

{

size++;

Node<T> *newNode = new Node<T> ( a );

if ( List<T>::empty() )

List<T>::first = List<T>::last = newNode;

else {

List<T>::first->prev = newNode;

newNode->next = List<T>::first;

List<T>::first = newNode;

}

}

template<typename T>

void countedList<T>::c_pop_front()

{

size--;

Node <T> *temp = List<T>::first;

List<T>::first = List<T>::first->next;

if ( List<T>::first != 0 )

List<T>::first->prev = 0;

else

List<T>::last = 0;

delete temp;

}

template<typename T>

void countedList<T>::c_insert(listIterator<T> &itr, T &a)

{

size++;

Node<T> *p = new Node<T> ( a );

Node<T> *current = itr.currentNode;

if ( List<T>::empty() ) { //empty list

List<T>::first = List<T>::last = p;

return;

}

//assert ( current );

if ( current == 0 ){ //point to end, thus append to list

List<T>::last->next = p;

p->next = 0;

p->prev = List<T>::last;

List<T>::last = p;

return;

}

//otherwise, always insert before

p->next = current;

p->prev = current->prev;

current->prev = p;

current = p->prev;

if ( current != 0 )

current->next = p;

else

List<T>::first = p;

}

template<typename T>

void countedList<T>::c_erase (listIterator<T> &start,listIterator<T> &stop)

//remove elements from the range ( before stop )

{

//List is friend of listIterator, so it can access listIterator's

// private or protected data member

Node<T> *p = start.currentNode;

Node<T> *q = p->prev;

Node<T> *stopNode = stop.currentNode;

if ( q == 0 ) { //removing initial portion of list

List<T>::first = stopNode;

if ( stopNode == 0 ) //pointing to end

List<T>::last = 0; //whole list is deleted

else

stopNode->prev = 0;

} else {

q->next = stopNode;

if ( stopNode == 0 )

List<T>::last = q;

else

stopNode->prev = q; // q->prev = q;

}

//now delete the atoms

while ( start != stop ) {

listIterator<T> next = start;

++next;

delete start.currentNode;

start = next;

--size;

}

}

//list_demo1.cpp

/*

Because of the use of template when defining the List and Node classes,

unfortunately, we do need to include the .cpp files here for the

current compilers.

*/

#include <iostream>

#include "list.cpp"

#include "Node.cpp"

#include "countedlist.cpp"

using namespace std;

template <typename T>

void print_list( countedList<T> &aList )

{

typename countedList<T>::iterator start, stop;

start = aList.begin(); stop = aList.end();

while ( start != stop ){

cout << *start << ",\t";

++start;

}

cout << endl;

}

int main()

{

typedef double T;

countedList<T> aList; //a list

T n;

while ( true ) {

cout << "Enter a number, -99 to terminate: ";

cin >> n;

if ( n == -99 )

break;

aList.c_push_front( n ); //insert into list at front

} //while

cout << "You have entered the list: " << endl;

print_list( aList );

listIterator<double> itr1;

listIterator<double> itr2;

itr2 = aList.begin();

itr1 = aList.end();

cout<<"The size of the list is: "<<aList.c_size()<<endl;

for(int i=0;i<aList.c_size()-1;i++){

++itr2;

}

cout<<"Deleting one item...\n";

aList.c_erase(itr2, itr1);

cout<<"The size of the list is: "<<aList.c_size()<<endl;

itr2 = aList.begin();

for(int i=0;i<aList.c_size()-2;i++){

++itr2;

}

cout<<"Deleting two items...\n";

aList.c_erase(itr2, itr1);

cout<<"The size of the list is: "<<aList.c_size()<<endl;

itr2 = aList.begin();

for(int i=0;i<aList.c_size()-3;i++){

++itr2;

}

cout<<"Deleting three items...\n";

aList.c_erase(itr2, itr1);

cout<<"The size of the list is: "<<aList.c_size()<<endl;

cout<<"Adding two items (0's')...\n";

n=0;

aList.c_insert(itr1,n);

itr1 = aList.end();

aList.c_insert(itr1, n);

cout<<"The size of the list is: "<<aList.c_size()<<endl;

//++itr2; ++itr2;

//aList.c_erase(itr2, itr1 );

print_list( aList );

cout<<"The size of the list is: "<<aList.c_size()<<endl;

return 0;

}

2. ( 15 points )

a) What is the postfix expression of the following?

(a * ( b + c ) + ( b / d ) * a / e

The postfix expression is: a, b, c, +, *, b, d, /, a, *, e, /, +

b) Write a complete program that can parse an arbitrary infix expression consisting of real

numbers, positive and negative, convert it to postfix and evaluate it ( see lab 8 ). Add to your

program a menu that have the following instructions:

(i) c -- clear all values from postfix queue,

(ii) d -- double front value of the postfix queue

Test your implementation with various infix input expressions.

//

//Kendall Small

#ifndef SYMBOL_H

#define SYMBOL_H

#include<string>

#include<queue>

#include<stack>

#include<stdio.h>

#include<ctype.h>

using namespace std;

typedef double dType; //Data type: int or double

enum inKind {operate, number}; //input kind

class SYMBOL{

public:

dType num; //stores numbers

inKind kind; //determines number or operator

char operatr; //stores operators

};

void in2postFix(stack<SYMBOL> &ifix, queue<SYMBOL> &pfix);

dType eval (queue<SYMBOL> &post);

#endif

//TOOLS_H

//Kendall Small

#include "symbol.h"

#ifndef TOOLS_H

#define TOOLS_H

void que2stack(queue<SYMBOL> &que, stack<SYMBOL> &s);

void reverse_stack(stack<SYMBOL> &s, stack<SYMBOL> &sr);

bool c_is_an_operator( char c);

void print_que(queue<SYMBOL> q);

void print_stack(stack<SYMBOL> s);

void double_first(queue<SYMBOL> &q);

void clear(queue<SYMBOL> &q);

#endif

//in2postfix.cpp

#include "symbol.h"

int precedence(char c){

switch(c){

case '+':

case '-':

return 1;

case '*':

case '/':

return 2;

}

return 0; //lowest precedence

}

void transfer(stack<SYMBOL> &s, queue<SYMBOL> &q){

q.push(s.top());

s.pop(); //Add top stack elem to queue, then delete

}

void in2postFix(stack<SYMBOL> &ifix, queue<SYMBOL> &pfix){

stack<SYMBOL> opStack; //stack of operators

SYMBOL a;

while(!ifix.empty()){

a=ifix.top(); //get next operator/operand from infix

ifix.pop(); //remove(delete) the top operator/operand

if(a.kind==number){pfix.push(a);} //to postfix queue

else if(opStack.empty()){opStack.push(a);} //to operator stack

else if(a.operatr=='('){opStack.push(a);} //Since ( lowest precedence

else if(a.operatr==')'){ //

while(opStack.top().operatr != '(')

transfer (opStack, pfix);

opStack.pop(); //transfer ( and remove

} else {

while(!opStack.empty()&&precedence(a.operatr)<=precedence(opStack.top().operatr))

transfer(opStack, pfix);

opStack.push(a);

}

}//while

while(!opStack.empty())

transfer(opStack, pfix);

}

//eval.cpp

//Kendall Small

#include "tools.h"

#include "symbol.h"

//Evaluate postfix expression

dType eval(queue<SYMBOL> &post){

stack<SYMBOL> eval;

dType a, b, ans;

char binaryOp; //binary operators +,=,*,/

SYMBOL symPop, symEval; //symbols popped element and evaluate

while(!post.empty()){

symPop=post.front();

post.pop();

if(symPop.kind==number)

eval.push(symPop); //save numbers until operator is found

else {

symEval = eval.top(); //gets a number to evaluate

a = symEval.num;

eval.pop();

symEval=eval.top(); //another number to evaluate

b = symEval.num;

eval.pop();

binaryOp=symPop.operatr;

switch(binaryOp){

case '-':

ans = b - a;

break;

case '+':

ans=b+a;

break;

case '/':

ans = b/a;

break;

case '*':

ans=b*a;

break;

}

symEval.num=ans; //answer goes back on until queue empty

eval.push(symEval);

}

}

symEval=eval.top();

return symEval.num;

}

//tools.cpp

//Kendall Small

#include "symbol.h"

#include "tools.h"

#include<iostream>

using namespace std;

void double_first(queue<SYMBOL> &q){

SYMBOL temp = q.front();

if(q.front().operatr == operate){

cout<<"Cannot double an operator.\n";

}

else

q.front().num *= 2;

}

void clear(queue<SYMBOL> &q){

while(!q.empty()){

q.pop();

}

}

void que2stack(queue<SYMBOL> &q, stack<SYMBOL> &s){

SYMBOL sym;

while(!q.empty()){

sym=q.front();

q.pop();

s.push(sym);

}

}

void reverse_stack(stack<SYMBOL> &s, stack<SYMBOL> &sr){

SYMBOL sym;

while(!s.empty()){

sym=s.top();

sr.push(sym);

s.pop();

}

}

bool c_is_an_operator(char c){

if(c=='(' || c==')' || c=='+' || c=='*' || c=='/' || c=='-')

return true;

return false;

}

void print_que(queue<SYMBOL> q){

while(!q.empty()){

SYMBOL s=q.front();

q.pop();

if(s.kind==number)

cout<<s.num<<" ";

else

cout<<s.operatr<< " ";

}

cout<<endl;

}

void print_stack(stack<SYMBOL> s){

while(!s.empty()){

SYMBOL a= s.top();

s.pop();

if(a.kind==number)

cout<<a.num<<" ";

else

cout<<a.operatr<<" ";

}

cout<<endl;

}

//Infix to postfix program main.cpp

//Kendall Small

#include "symbol.h"

#include "tools.h"

#include <iostream>

using namespace std;

int main() {

stack<SYMBOL> sym, s1;

queue<SYMBOL> que;

SYMBOL s;

char c, select, again;

double x, xInt, xFrac, fracD;

int dotFlag, readFlag, numFlag, sign, lpFlag;

dType ans;

do{

cout<<"Enter an infix expression using real numbers\n";

cout<<"Every negative number after the first must be inside parenthesis\n";

cout<<"For example: -1*(3 + (-4))\n";

x=xInt=xFrac=0;

fracD=0.1;

dotFlag=numFlag=0;

lpFlag=0;

while((c=getchar())==' ');

if(c=='-'){

sign=-1;

c=getchar();

} else

sign=1;

while(true){

if(c=='.') dotFlag=1;

if(isdigit(c)){

if(!dotFlag)

xInt=xInt*10+(c-'0');

else {

xFrac+=(c-'0')*fracD;

fracD*=0.1;

}

numFlag=1;

}else

if((numFlag==1)&&(c!='.')){

x=xInt+xFrac;

s.num=x*sign;

s.kind=number;

sym.push(s);

sign=1;

fracD=0.1;

x=xInt=xFrac=0.0;

dotFlag=numFlag=0;

}else if(c=='('){

while((c=getchar())==' ');

if(c=='-'){

lpFlag=1;

sign=-1;

c=getchar();

continue;

}else{

ungetc(c,stdin);

c='(';

}

}//(c=='(')

if(c_is_an_operator(c)){

if(!lpFlag){

s.operatr=c;

s.kind=operate;

sym.push(s);

}

lpFlag=0;

}

if(c=='\n')break;

c=getchar();

}//while(true)

reverse_stack(sym, s1);

cout<<"The infix expression you entered was: ";

print_stack(s1);

in2postFix(s1, que);

cout<<"Please select an option: \n";

cout<<"Enter: c -- clear all values from postfix queue (start again)\n";

cout<<"Enter: d -- double the value in the first spot of the postfix queue\n";

cout<<"Anything else will finish the program as usual, giving output.\n";

cin>>select;

switch(select){

case 'c':

case 'C':{

clear(que);

cout<<"Printing empty postfix queue: ";

print_que(que);

cout<<"If nothing printed then postfix queue successfully cleared.\n";

break;

}

case 'd':

case 'D':{

cout<<"Postfix queue before: \n";

print_que(que);

double_first(que);

cout<<"Postfix expression after doubling: \n";

print_que(que);

cout<<"The answer is: "<<eval(que)<<endl;

break;

}

default:{

cout<<"After conversion the postfix expression is: ";

print_que(que);

cout<<"The answer is: "<<eval(que)<<endl;

break;

}

}//switch

cout<<"Again? (Y/N)\n";

cin>>again;

cin.clear(); cin.ignore(INT_MAX,'\n');

}while(again == 'Y' || again=='y');

return 0;

}

3. ( 10 points ) Write a program that makes use of the functions of bitset to do the following:

a. it asks for an integer as input, prints out its value in 24-bit binary form and in 8-hex-digit

form;

b. it asks for a binary value as input and prints out its decimal value; it should be able to

handle binary values up to 32-bit.

//Bitset

//Kendall Small

#include<iostream>

#include<stdio.h>

#include<stdlib.h>

#include<string>

#include<bitset>

using namespace std;

int main() {

int toBinary, temp;

long fromBinary;

char hex[240];

string binary;

cout<<"Please enter an integer to be converted to 24-bit binary: \n";

cin>>toBinary;

bitset<24> intSet(toBinary);

cout<<"The integer "<<toBinary<<" is equal to "<<intSet<<" in binary form.\n";

bitset<32> hexSet(toBinary);

cout<<"The integer "<<toBinary<<" is equal to hex: ";//<<hex<<" in hex form.\n";

for(int i=31;i>=0;i-=4){

bitset<4> t;

for(int j=i;j>(i-4);j--){

t[j%4]=hexSet[j];

}

fromBinary=t.to_ulong();

itoa(fromBinary,hex, 16);

cout<<hex<<" ";

}

cout<<endl<<endl;

cin.clear();

cin.ignore(INT_MAX,'\n');

cout<<"Enter a string of binary up to 32 bits long: \n";

getline(cin, binary);

bitset<32> stringSet(binary);

fromBinary = stringSet.to_ulong();

cout<<"The binary "<<binary<<" is equal to "<<fromBinary<<" in base 10.\n";

return 0;

}

4. ( 10 points ) Write a program that makes use of a backtrack algorithm to see if you can put 10

queens on a hypothetical 10x10 square chess board with no queen threatening any other. If

there's a solution, prints out the solution.

//Backtracking algorithm

//Kendall Small

#include <iostream>

using namespace std;

class nQueen{

public:

nQueen();

void clear();

void printBoard();

void setPiece(int col, bool &verdict);

bool answer(int);

private:

int n; //size

char board[10][10];

void set(int col, int row){board[row][col]='X';}

void get(int col, int row){board[row][col]='-';}

bool danger(int col, int row);

};

nQueen::nQueen(){

n=10; //change size here as well

for(int i=0;i<n;i++){

for(int j=0;j<n;j++){

board[i][j] = '-';

}

}

}

void nQueen::printBoard(){

for(int i=0;i<n;i++){

for(int j=0;j<n;j++){

cout<<board[i][j]<<" ";

}

cout<<"\n";

}

}

bool nQueen::danger(int r, int c){

int a, b;

for(a=0;a<c;a++){

if(board[r][a]=='X')

return true;

}

for(a=r, b=c;a>=0 && b>=0;a--, b--){

if(board[a][b]=='X')

return true;

}

for(a=r, b=c;b>=0 && a<n;a++, b--){

if(board[a][b]=='X')

return true;

}

return false;

}

bool nQueen::answer(int col){

if(col>=n){

return true;

}

for(int a=0;a<n;a++){

if(danger(a, col)==false){

set(col, a);

//board[a][col]= 'X';

if(answer(col+1)==true)

return true;

get(col, a);

//board[a][col]='-';

}

}

return false;

}

int main() {

nQueen ten;

bool verdict;

verdict = ten.answer(0);

if(verdict==true)

ten.printBoard();

else

cout<<"There is no solution.\n";

return 0;

}