//Sucessfully tested in Dev-C++ under ISO C++11 #include #include #include #include //create random number #include //for 'throw' #include class Student //specialization(in problem 1) { private: char *id, *name, *schoolName; double discountRate; public: Student():id(nullptr), name(nullptr), schoolName(nullptr), discountRate(1.0) {} Student(double _discountRate):id(nullptr), name(nullptr), schoolName(nullptr), discountRate(_discountRate) {} ~Student() {} }; template class MyVector //template class { private: T data[100] = {}; //each vector is small that no need to preallocate unsigned size, capacity; public: MyVector(): size(0), capacity(100) {} MyVector(const MyVector& x): size(x.size), capacity(x.capacity) //copy constructor for deep copy { data = new T[capacity]; std::copy(x.data, x.data + size, data); } ~MyVector() {} void insert(const T& value, unsigned index) { if(size >= capacity) std::cout<<"Error: line 37, already full."<<"\t"< size) std::cout<<"Error: line 38, invalid index."<<"\t"<index;--i) data[i] = data[i-1]; //'std::copy' can be used here data[index] = value; ++size; } void erase(unsigned index) { if(index >= size) std::cout<<"Error: line 45, invalid index."<= size) throw std::out_of_range("Index out of range"); return data[index]; } unsigned getSize() const {return size;} //get the size of the vector unsigned getCapacity() const {return capacity;} //get the capacity of the vector }; template struct Node { MyVector vec; //'std::unique_ptr' can be used here unsigned size; Node *prev, *next; Node(): size(0), prev(nullptr), next(nullptr), vec() {} }; template class ListQueue { private: Node *head, *tail; //bidirectional unsigned allSize; //decrease use of ListQueue::size() public: ListQueue(): head(nullptr), tail(nullptr), allSize(0) {} ~ListQueue() { Node *temp=head; while(temp) { Node *next=temp->next; delete temp; temp = next; } } void push_front(const T& value) { if(!head || head->size >= 100) { Node *newNode=new Node(); newNode->vec.insert(value, 0); if(!head) head = tail = newNode; else { newNode->next = head; head->prev = newNode; head = newNode; } newNode->size = 1; } else { head->vec.insert(value, 0); ++head->size; } ++allSize; } void push_back(const T& value) { if(!tail || tail->size >= 100) { Node *newNode=new Node(); newNode->vec.insert(value, 0); if(!tail) head = tail = newNode; else { newNode->prev = tail; tail = newNode; } newNode->size = 1; } else { tail->vec.insert(value, tail->size); ++tail->size; } ++allSize; } void pop_back() { if(!tail) return; tail->vec.erase(tail->size-1); --tail->size; if(tail->size == 0) { Node *temp=tail; tail = tail->prev; if(tail) tail->next = nullptr; delete temp; if(!tail) head = nullptr; } --allSize; } void pop_front() { if(!head) return; head->vec.erase(0); --head->size; if(head->size == 0) { Node* temp = head; head = head->next; if(head) head->prev = nullptr; delete temp; if(!head) tail = nullptr; } --allSize; } void insert(const T& value, unsigned index) { if(!head || index >= size()) { push_back(value); return; } Node *current=head; unsigned totalSize=0; while(current) { totalSize += current->size; unsigned t=current->size; //'current->size' may be changed in process if(index < totalSize) { if(current->size >= 100) { Node *newNode=new Node(); unsigned splitIndex=index-(totalSize-current->size); MyVector& vec=current->vec; for(unsigned i=splitIndex;i<100;++i) { int m=0; newNode->vec.insert(vec[i], m++); //'std::memcpy' can be used here ++newNode->size; } for(unsigned i=splitIndex;i<100;++i) { vec.erase(splitIndex); --current->size; } newNode->next = current->next; if(current->next) current->next->prev = newNode; current->next = newNode; newNode->prev = current; if(tail == current) tail = newNode; } current->vec.insert(value, index-(totalSize-t)); ++current->size; ++allSize; return; } current = current->next; } } void erase(unsigned index) { if(!head || index >= size()) return; Node *current=head; unsigned totalSize=0; while(current) { totalSize += current->size; if (index < totalSize) { unsigned targetIndex=index-(totalSize-current->size); current->vec.erase(targetIndex); --current->size; if(current->size == 0) { if(current == head) { head = head->next; if(head) head->prev = nullptr; } else if(current == tail) { tail = tail->prev; if(tail) tail->next = nullptr; } else { current->prev->next = current->next; current->next->prev = current->prev; } delete current; } --allSize; return; } current = current->next; } } unsigned size() const //at least O(n) { if(!head) return 0; unsigned totalSize=0; Node *current=head; while(current) { totalSize += current->size; current = current->next; } return totalSize; } unsigned getSize() const {return allSize;} //only O(1) T& operator[](unsigned index) { if(!head || index >= size()) throw std::out_of_range("Index out of range"); Node *current=head; unsigned totalSize=0; while(current) { totalSize += current->size; if (index < totalSize) return current->vec[index-(totalSize-current->size)]; current = current->next; } throw std::out_of_range("Index out of range"); } friend std::ostream& operator<<(std::ostream& out, const ListQueue& queue) { Node *current=queue.head; out<<"ListQueue: "; while(current) { for(unsigned i=0;isize;++i) out<vec[i]<<" "; current = current->next; } return out; } void print(std::ostream& os) const //print on screen or in file { Node *current=head; unsigned nodeCount=0; os<size<next; } os<<"All Nodes: "< *test1=new ListQueue(); unsigned testTurn=100000; std::cout< elements at random positions to "< ListQueue_result.txt"<"<getSize() < testTurn) { unsigned randomIndex=test1->getSize()==0?0:rand()%test1->getSize(); //always valid index surance unsigned randomValue=rand()%1000+1; //assuming range 1-1000 for elements if(test1->getSize() % (testTurn / 100) == 0) std::cout<getSize()/(testTurn/100)<<"% has completed."<getSize()<insert(randomValue, randomIndex); } test1->print(os); std::cout< elements at random positions to 0. Process begins and may require a while of waiting time."<getSize()) { unsigned randomIndex=rand()%test1->getSize(); //always valid index surance if(test1->getSize() % (testTurn / 100) == 0) std::cout<<100-test1->getSize()/(testTurn/100)<<"% has completed."<getSize()<erase(randomIndex); } test1->print(os); std::cout< *test2=new ListQueue(); testTurn = 100000; std::cout< elements at random positions to "< ListQueue_result.txt"<"<getSize() < testTurn) { unsigned randomIndex=test2->getSize()==0?0:rand()%test2->getSize(); //always valid index surance unsigned randomValue=1.0*(rand()%1000+1); //assuming range 1-1000 for elements if(test2->getSize() % (testTurn / 100) == 0) std::cout<getSize()/(testTurn/100)<<"% has completed."<getSize()<insert(randomValue, randomIndex); } std::cout<getSize()/(testTurn/100)<<"% has completed."<print(os); std::cout< elements at random positions to 0. Process begins and may require a while of waiting time."<getSize()) { unsigned randomIndex=rand()%test2->getSize(); //always valid index surance if(test2->getSize() % (testTurn / 100) == 0) std::cout<<100-test2->getSize()/(testTurn/100)<<"% has completed."<getSize()<erase(randomIndex); } std::cout<<100-test2->getSize()/(testTurn/100)<<"% has completed."<print(os); std::cout< *test3=new ListQueue(); testTurn = 100000; std::cout< elements at random positions to "< ListQueue_result.txt"<"<getSize() < testTurn) { unsigned randomIndex=test3->getSize()==0?0:rand()%test3->getSize(); //always valid index surance unsigned randomValue=1.0*(rand()%1000+1); //assuming range 1-1000 for elements if(test3->getSize() % (testTurn / 100) == 0) std::cout<getSize()/(testTurn/100)<<"% has completed."<getSize()<insert(student, randomIndex); } std::cout<getSize()/(testTurn/100)<<"% has completed."<print(os); std::cout< elements at random positions to 0. Process begins and may require a while of waiting time."<getSize()) { unsigned randomIndex=rand()%test3->getSize(); //always valid index surance if(test3->getSize() % (testTurn / 100) == 0) std::cout<<100-test3->getSize()/(testTurn/100)<<"% has completed."<getSize()<erase(randomIndex); } std::cout<<100-test3->getSize()/(testTurn/100)<<"% has completed."<print(os); std::cout< ListQueue_result.txt"< test1; for(int i=1;i<=10;++i) test1.push_back(i); test1.pop_front(); test1.push_front(5); test1.pop_back(); test1.push_back(11); test1.insert(20, 5); os<