add List.h ListNode.h test_list.cpp, sorting algorithms still remain to be added.

This commit is contained in:
Shine wOng
2019-05-18 18:24:00 +08:00
parent ba403fcde0
commit 1175404193
3 changed files with 418 additions and 0 deletions

221
thu_dsa/chp3/List.h Normal file
View File

@@ -0,0 +1,221 @@
#ifndef LIST_H_
#define LIST_H_
#include "ListNode.h"
template <typename T>
class List{
private:
ListNodePosi(T) head;
ListNodePosi(T) tail;
int size;
protected:// internal methods
public:
//constructors
List(); // empty List
List(List const &L); // copy from another List
List(List const &L, int rank, int n); // copy n elements from L[rank]
List(ListNodePosi(T) p, int n); // copy n elements from position p
//deconstructor
~List();
//read-only interfaces
ListNodePosi(T) first() const { return head->succ; }
ListNodePosi(T) last() const { return tail->prev; }
ListNodePosi(T) find(T const &val) const { return find(val, size, tail); } //find val from all elements of the list
ListNodePosi(T) find(T const &val, int n, ListNodePosi(T) p) const; //find val from a range of n elements before p
T& operator[](int rank);
int getSize() const { return size; }
bool empty() const { return size == 0; }
//writable interfaces
//insert and delete operations
ListNodePosi(T) push_back(T const &val);
ListNodePosi(T) push_front(T const & val);
ListNodePosi(T) insert_before(int rank, T const &val);
ListNodePosi(T) insert_before(ListNodePosi(T) p, T const &val);
ListNodePosi(T) pop_back();
ListNodePosi(T) pop_front();
ListNodePosi(T) pop(int rank);
ListNodePosi(T) pop(ListNodePosi(T) p);
//deduplicate & uniquify
int deduplicate();
int uniquify();
};
/*----------implementations of class List----------*/
//constructors
template <typename T>
List<T>::List(){
tail = new ListNode<T>();
head = new ListNode<T>();
tail->prev = head;
head->succ = tail;
size = 0;
}
template <typename T>
List<T>::List(List const &L) {
tail = new ListNode<T>();
head = new ListNode<T>();
tail->prev = head;
head->succ = tail;
size = 0;
ListNodePosi(T) p = L.head->succ;
for (int ix = 0, size = L.getSize(); ix != size; ++ix, p = p->succ)
push_back(p->val);
}
template <typename T>
List<T>::List(List const &L, int rank, int n){
ListNodePosi(T) p = L.head->succ;
while (rank--) p = p->succ;
tail = new ListNode<T>();
head = new ListNode<T>();
tail->prev = head;
head->succ = tail;
size = 0;
for (int ix = 0; ix != n; ++ix, p = p->succ)
push_back(p->val);
}
template <typename T>
List<T>::List(ListNodePosi(T) p, int n){
tail = new ListNode<T>();
head = new ListNode<T>();
tail->prev = head;
head->succ = tail;
size = 0;
for (int ix = 0; ix != n; ++ix, p = p->succ)
push_back(p->val);
}
//deconstructor
template <typename T>
List<T>::~List(){
while (size) pop_back();
}
//read-only interfaces
template <typename T>
ListNodePosi(T) List<T>::find(T const &val, int n, ListNodePosi(T) p) const {
while ((p = p->prev) != head && n--)
if (p->val == val) return p;
return nullptr;
}
template <typename T>
T& List<T>::operator[](int rank){
ListNodePosi(T) p = head->succ;
while (rank--) p = p->succ;
return p->val;
}
// writable interfaces
//insert and delete operations
template <typename T>
ListNodePosi(T) List<T>::push_back(T const &val){
++size;
return tail->insertAsPred(val);
}
template <typename T>
ListNodePosi(T) List<T>::push_front(T const &val) {
++size;
return head->insertAsSucc(val);
}
template <typename T>
ListNodePosi(T) List<T>::pop_back() {
if (empty()) return nullptr;
ListNodePosi(T) res = tail->prev;
res->prev->succ = tail;
tail->prev = res->prev;
--size;
return res;
}
template <typename T>
ListNodePosi(T) List<T>::pop_front() {
if (empty()) return nullptr;
ListNodePosi(T) res = head->succ;
head->succ = res->succ;
res->succ->prev = head;
--size;
return res;
}
template <typename T>
ListNodePosi(T) List<T>::insert_before(int rank, T const &val){
ListNodePosi(T) p = head->succ;
while (rank--) p = p->succ;
return insert_before(p, val);
}
template <typename T>
ListNodePosi(T) List<T>::insert_before(ListNodePosi(T) p, T const &val){
++size;
return p->insertAsPred(val);
}
template <typename T>
ListNodePosi(T) List<T>::pop(int rank){
if (rank >= size || rank < 0) return nullptr;
ListNodePosi(T) p = head->succ;
while (rank--) p = p->succ;
return pop(p);
}
template <typename T>
ListNodePosi(T) List<T>::pop(ListNodePosi(T) p){
p->prev->succ = p->succ;
p->succ->prev = p->prev;
--size;
return p;
}
//deduplicate & uniquify
template <typename T>
int List<T>::deduplicate(){
int oldSize = size;
ListNodePosi(T) p = head->succ;
ListNodePosi(T) tmp;
for (; p != tail; p = p->succ){
for(tmp = head->succ; tmp != p; tmp = tmp->succ){
if(tmp->val == p->val){
pop(tmp);
break;
}
}
}
return oldSize - size;
}
template <typename T>
int List<T>::uniquify(){
if (empty()) return 0;
int oldSize = size;
ListNodePosi(T) p = head->succ;
while ((p = p->succ) != tail)
if (p->val == p->prev->val) pop(p);
return oldSize - size;
}
#endif

55
thu_dsa/chp3/ListNode.h Normal file
View File

@@ -0,0 +1,55 @@
#ifndef LISTNODE_H_
#define LISTNODE_H_
#define ListNodePosi(T) ListNode<T>*
template <typename T>
class ListNode{
public:
ListNodePosi(T) prev;
ListNodePosi(T) succ;
T val;
//constructor
ListNode();
ListNode(T val, ListNodePosi(T) const &p = nullptr, ListNodePosi(T) const &s = nullptr);
//external interfaces
ListNodePosi(T) insertAsPred(T const &val);
ListNodePosi(T) insertAsSucc(T const &val);
};
/*----------implementation of class ListNode----------*/
//constructor
template <typename T>
ListNode<T>::ListNode(){
prev = nullptr;
succ = nullptr;
}
template <typename T>
ListNode<T>::ListNode( T v, ListNodePosi(T) const &p = nullptr, ListNodePosi(T) const &s = nullptr ){
val = v;
prev = p;
succ = s;
}
//external interfaces
template <typename T>
ListNodePosi(T) ListNode<T>::insertAsPred(T const &val){
ListNodePosi(T) newNode = new ListNode<T>(val, prev, this);
prev->succ = newNode;
prev = newNode;
return newNode;
}
template <typename T>
ListNodePosi(T) ListNode<T>::insertAsSucc(T const &val){
ListNodePosi(T) newNode = new ListNode(val, this, succ);
succ->prev = newNode;
succ = newNode;
return newNode;
}
#endif

142
thu_dsa/chp3/test_list.cpp Normal file
View File

@@ -0,0 +1,142 @@
#include "List.h"
#include <iostream>
#include <cassert>
using std::cout;
using std::endl;
void test_constructor1();
void test_constructor2();
void test_push();
void test_pop();
void test_find();
void test_deduplicate();
void test_uniquify();
int main(){
cout << "Running tests......" << endl;
test_constructor1();
test_constructor2();
test_push();
test_pop();
test_find();
test_deduplicate();
test_uniquify();
cout << "All tests passed." << endl;
system("pause");
return 0;
}
void test_constructor1(){
List<double> l;
assert(l.getSize() == 0);
assert(l.empty());
}
void test_constructor2(){
List<int> l1;
int i[] = { 5,6,8,9,7,3,4,1,2,0 };
for (int ix = 0; ix != 10; ix++)
l1.push_back(i[ix]);
List<int> l2(l1);
for (int ix = 0; ix != 10; ix++)
assert(l2[ix] == i[ix]);
List<int> l4(l1.first(), 5);
for (int ix = 0; ix != 5; ix++)
assert(l4[ix] == i[ix]);
assert(l4.getSize() == 5);
List<int> l5(l1.last(), 1);
assert(l5.getSize() == 1);
assert(l5.first()->val == 0);
List<int> l3(l1, 3, 6);
assert(l3.getSize() == 6);
for (int ix = 0; ix != 6; ix++)
assert(l3[ix] == i[3+ix]);
}
void test_push(){
List<double> l;
double d[] = { 1.2, 3.4, 5.6, 7.8, 9.0 };
for (int ix = 0; ix != 5; ix++)
l.push_back(d[ix]);
for (int ix = 0; ix != 5; ix++)
assert(l[ix] == d[ix]);
List<int> l1;
int i[] = { 5,6,8,9,7,3,4,1,2,0 };
for (int ix = 0; ix != 10; ix++)
l1.push_front(i[ix]);
for (int ix = 0; ix != 10; ix++)
assert(l1[ix] == i[9-ix]);
//test insert_before
assert(l1.insert_before(0, 12)->val == 12);
assert(l1.getSize() == 11);
assert(l1.insert_before(11, 14)->val == 14);
assert(l1.getSize() == 12);
}
void test_pop(){
List<int> l1;
int i[] = { 5,6,8,9,7,3,4,1,2,0 };
for (int ix = 0; ix != 10; ix++)
l1.push_back(i[ix]);
assert(l1.pop_back()->val == 0);
assert(l1.pop_back()->val == 2);
assert(l1.pop_front()->val == 5);
assert(l1.pop_front()->val == 6);
assert(l1.getSize() == 6);
assert(l1.pop(3)->val == 3);
assert(l1.pop(5) == nullptr);
ListNodePosi(int) p = l1.first();
assert(l1.pop(p)->val == 8);
}
void test_find(){
List<int> l1;
int i[] = { 5,6,8,9,7,3,4,1,2,0 };
for (int ix = 0; ix != 10; ix++)
l1.push_back(i[ix]);
assert(l1.find(8)->val == 8);
assert(l1.find(7)->val == 7);
assert(l1.find(12) == nullptr);
assert(l1.find(7, 5, l1.last())->val == 7);
assert(l1.find(7, 4, l1.last()) == nullptr);
}
void test_deduplicate(){
List<int> l1;
int i[] = { 5,6,8,9,7,3,4,1,2,0};
for (int ix = 0; ix != 10; ix++) {
l1.push_front(i[ix]);
l1.push_back(i[ix]);
}
assert(l1.getSize() == 20);
assert(l1.deduplicate() == 10);
assert(l1.getSize() == 10);
for (int ix = 0; ix != 10; ix++)
assert(l1[ix] == i[ix]);
}
void test_uniquify(){
List<int> l1;
int i[] = {5,8,12,14,15,19,20,22,29,36};
for (int ix = 0; ix != 11; ix++) {
l1.push_back(i[ix]);
l1.push_back(i[ix]);
}
assert(l1.getSize() == 22);
assert(l1.uniquify() == 11);
for (int ix = 0; ix != 11; ix++)
assert(l1[ix] == i[ix]);
}