C++手写实现模板类+迭代器(十字矩阵链表)

今天接到一个单,是纯手写实现一个比较复杂的模板类

想也没想就接了下来,因为之前只是听说过模板类,但是自己也没有敲过,毕竟ACM的算法也不会涉及到那方面

花十分钟先找了些实现模板类的博客看了一下,然后就跟着给的测试用例开始写

真正开始写才发现,这东西是真tm难

特别是迭代器部分,网上基本找不到有关的实现

从晚上十点半写到现在凌晨五点也只写了200+行

两个通宵4000字五百行写出的玩意儿

完整版(+注释)

grid.h

#include <iostream>
#include <iomanip> 
using namespace std;

// 十字链表节点,flag用于螺旋迭代器,为0表示当前节点未经过,为1表示当前节点已经走过
template <class T>
struct node {
	int flag;
	T val;
	node *up, *down, *left, *right;
	// 默认构造函数
	node() :up(nullptr), down(nullptr), left(nullptr), right(nullptr), flag(0) {}
	// 带参构造函数
	node(T val) {
		this->val = val;
		up = down = left = right = nullptr;
		flag = 0;
	}
};

// 十字链矩阵模板类
template <class T>
class Grid {
private:
	// 矩阵的长宽和面积
	int width, height, size;
	// 指向矩阵四角的四个指针
	node<T> *upper_left, *upper_right, *lower_left, *lower_right;
public:
	// 迭代器子类
	class iterator {
	public:
		// dir 和 mode 是用于蛇形迭代器和螺旋迭代器的,mode 表示迭代器类型,dir 表示迭代器的当前方向
		// 当 mode 值为 0 时是普通迭代器,当 mode 值为 1 时是蛇形迭代器, 当 mode 值为 2 时是螺旋迭代器
		int dir, mode;
		// itr 是迭代器的核心指针,pre 是一个辅助指针
		node<T> *itr, *pre;
		// 迭代器的 set 函数就是把当前指针的值修改
		void set(T val) { itr->val = val; }

		// 下面四个函数是迭代器的移动操作,返回值是当前迭代器的引用,便于连续操作
		iterator& left() {
			itr = itr->left;
			return *this;
		}
		iterator& right() {
			itr = itr->right;
			return *this;
		}
		iterator& up() {
			itr = itr->up;
			return *this;
		}
		iterator& down() {
			itr = itr->down;
			return *this;
		}

		// 迭代器默认构造函数,默认构造一个普通迭代器
		iterator() :itr(nullptr), pre(nullptr), mode(0) {}

		// 重载迭代器的 = 操作
		void operator=(node<T> *it) {
			// 使用指针 = 的时候一般都是普通迭代器
			mode = 0;
			dir = 0;
			// 当这个指针为空,就不用继续了
			if (it == nullptr)
				return;
			// 当这个指针不为空的时候,找到当前指针的最左段,并把辅助指针复制为最左端的下面一个,方便之后 ++ 操作
			node<T> *p = it;
			while (p->left != nullptr)
				p = p->left;
			itr = it;
			pre = p->down;
		}
		// 重载迭代器的 != 和 == 操作
		bool operator!=(const iterator& it) { return this->itr != it.itr; }
		bool operator==(const iterator& it) { return this->itr == it.itr; }
		// 重载迭代器的 * 操作,返回一个模板类的引用,方便赋值、判断等操作
		T& operator*() { return itr->val; }
		// 重载迭代器的 ++ 操作
		void operator++(int) {
			// 普通迭代器,靠辅助指针,每次到了这一行最后可以直接跳到下一行的最左边
			// 辅助指针只需要在 = 操作时,增加一些操作就可以让 ++ 操作简化到 O1 的复杂度
			if (mode == 0) {
				if (itr->right == nullptr) {
					itr = pre;
					// 如果到了最后一行,那么下一行得最左端肯定是个空指针
					// 如果再执行这一步就会出现指针越界
					if (pre)
						pre = pre->down;
				}
				else
					itr = itr->right;
			}
			// 蛇形迭代器,触底就变向,这个不用说太细
			else if (mode == 1) {
				if (dir == 0) {
					if (itr->right == nullptr)
						itr = itr->down, dir = 1;
					else
						itr = itr->right;
				}
				else {
					if (itr->left == nullptr)
						itr = itr->down, dir = 0;
					else
						itr = itr->left;
				}
			}
			// 螺旋迭代器,靠着在创建节点时的辅助标记 (node 中的 flag), 让这个 ++ 操作变成了 O1 的复杂度
			// 但是在 begin_spiral 中需要一次 O(W*H) 的复杂度对矩阵中所有节点的 flag 进行一次初始化
			// 每次到一个节点经过之后赋值为 1,所以每当当前方向之前的节点的 flag 为 1 或是为空就变向就可以了
			else if (mode == 2) {
				// 空指针返回空
				if (itr == nullptr)
					itr = nullptr;
				// 当周围四个方向都不能走时,说明已经走完了整个矩阵了,所以变成空指针就可以了
				else if ((itr->right == nullptr || itr->right->flag == 1) && (itr->down == nullptr || itr->down->flag == 1) && (itr->left == nullptr || itr->left->flag == 1) && (itr->up == nullptr || itr->up->flag == 1))
					itr = nullptr;
				// 下面为 4 个方向的具体实现,撞墙就转向,不装就继续往前走,代码很好懂的
				else if (dir == 0) {
					itr->flag = 1;
					if (itr->right == nullptr || itr->right->flag == 1)
						itr = itr->down, dir = 1;
					else
						itr = itr->right;
				}
				else if (dir == 1) {
					itr->flag = 1;
					if (itr->down == nullptr || itr->down->flag == 1)
						itr = itr->left, dir = 2;
					else
						itr = itr->down;
				}
				else if (dir == 2) {
					itr->flag = 1;
					if (itr->left == nullptr || itr->left->flag == 1)
						itr = itr->up, dir = 3;
					else
						itr = itr->left;
				}
				else if (dir == 3) {
					itr->flag = 1;
					if (itr->up == nullptr || itr->up->flag == 1)
						itr = itr->right, dir = 0;
					else
						itr = itr->up;
				}
			}
		}
	};

	// 具体实现在下面
	Grid();
	Grid(int n, int m);
	Grid(int n, int m, T val);
	~Grid();
	void print();
	T get(int n, int m);
	void set(int n, int m, T val);
	void join(Grid<T>& oth);
	void stack(Grid<T>& oth);
	void reset(T val);
	void lift(Grid<T>::iterator x, Grid<T>& oth);
	void chop(Grid<T>::iterator x, Grid<T>& oth);
	void clear();

	// 获得宽高面积,直接返回一个相应值就行了,复杂度O1
	int getWidth() { return this->width; }
	int getHeight() { return this->height; }
	int getSize() { return this->size; }

	// 返回一个普通迭代器,指向左上的起点
	iterator begin() {
		iterator x;
		x = upper_left;
		return x;
	}
	// 返回一个普通迭代器,指针域为空
	iterator end() {
		iterator x;
		return x;
	}
	// 返回一个蛇形迭代器,指向左上的起点
	// 注意把迭代器的 mode 设置为蛇形迭代器模式,初始方向向右
	iterator begin_snake() {
		iterator x;
		x = upper_left;
		x.mode = 1;
		x.dir = 0;
		return x;
	}
	// 返回一个空指针域的迭代器
	iterator end_snake() {
		return end();
	}
	// 返回一个螺旋迭代器,指向左上起点
	// 注意把迭代器的 mode 设置为螺旋迭代器模式,初始方向向右
	iterator begin_spiral() {
		iterator it = begin();
		// 这就是上面说到把矩阵所有节点的 flag 初始化的地方 复杂度 O(W*H)
		while (it != end())
			it.itr->flag = 0, it++;
		iterator x;
		x = upper_left;
		x.mode = 2;
		x.dir = 0;
		return x;
	}
	// 返回一个空指针域迭代器
	iterator end_spiral() {
		return end();
	}

	// 返回指向四角的迭代器
	iterator begin_upper_left() {
		iterator x;
		x = upper_left;
		return x;
	}
	iterator begin_upper_right() {
		iterator x;
		x = upper_right;
		return x;
	}
	iterator begin_lower_left() {
		iterator x;
		x = lower_left;
		return x;
	}
	iterator begin_lower_right() {
		iterator x;
		x = lower_right;
		return x;
	}
};

// 默认构造函数,四角默认为空指针,宽高面积为 0
template <class T>
Grid<T>::Grid() {
	upper_left = nullptr; upper_right = nullptr;
	lower_left = nullptr; lower_right = nullptr;
	width = height = size = 0;
}
// 只有宽高的构造函数,默认填充的为 int 0
template <class T>
Grid<T>::Grid(int n, int m) {
	width = n; height = m; size = n * m;
	// 三个辅助指针,pre表示上一层相应位置节点,up为上一层最左端点,q为左边一个节点
	// 用于将当前节点与前面和上面的节点链接起来
	node<T> *pre = nullptr, *up = nullptr, *q = nullptr;
	for (int a = 0; a < m; a++) {
		// pre初始化为上一层最左端点
		pre = up;
		for (int b = 0; b < n; b++) {
			node<T> *p = new node<T>(0);
			// 把左上指针指向当前节点
			if (a == 0 && b == 0)
				upper_left = p;
			// 把右上指针指向当前节点
			if (a == 0 && b == n - 1)
				upper_right = p;
			// 把左下指针指向当前节点
			if (a == m - 1 && b == 0)
				lower_left = p;
			// 把右下指针指向当前节点
			if (a == m - 1 && b == n - 1)
				lower_right = p;
			// 第一竖排,前面没有节点可供链接
			if (b == 0) {
				// up每次赋值为最左端点,下一次循环 pre 赋值时就变成了上一层的最左端点
				up = p, q = p;
				// 第一横排之后才需要和上一层的节点链接
				if (a != 0)
					p->up = pre, pre->down = p, pre = pre->right;
			}
			else {
				if (a != 0)
					p->up = pre, pre->down = p, pre = pre->right;
				p->left = q, q->right = p, q = q->right;
			}
		}
	}
}
// 和上面的流程一样,只是带上了值,就不重复写了
template <class T>
Grid<T>::Grid(int n, int m, T val) {
	width = n; height = m; size = n * m;
	node<T> *pre = nullptr, *up = nullptr, *q = nullptr;
	for (int a = 0; a < m; a++) {
		pre = up;
		for (int b = 0; b < n; b++) {
			node<T> *p = new node<T>(val);
			if (a == 0 && b == 0)
				upper_left = p;
			if (a == 0 && b == n - 1)
				upper_right = p;
			if (a == m - 1 && b == 0)
				lower_left = p;
			if (a == m - 1 && b == n - 1)
				lower_right = p;
			if (b == 0) {
				up = p, q = p;
				if (a != 0)
					p->up = pre, pre->down = p, pre = pre->right;
			}
			else {
				p->left = q, q->right = p, q = q->right;
				if (a != 0)
					p->up = pre, pre->down = p, pre = pre->right;
			}
		}
	}
}
// 析构函数,不能边遍历边删除内存,因为删除之后,之前的节点就不存在了,用++就无法跳到下一个
// 所以用一个指针数组,遍历一遍把所有指针存起来,然后再挨个删除,复杂度为 O(W*H)
// clear()函数和这个析构函数一模一样下面就不重复了
template <class T>
Grid<T>::~Grid() {
	iterator it = begin();
	node<T>*ve[10000];
	int len = 0;
	// 遍历矩阵,把每个指针都存入指针数组
	while (it != end())
		ve[len++] = it.itr, it++;
	// 挨个删除节点内存
	for (int a = 0; a < len; a++)
		delete ve[a];
	// 初始化长宽面积和四角指针
	width = height = size = 0;
	upper_left = upper_right = nullptr;
	lower_left = lower_right = nullptr;
}
// 打印函数,遍历打印就行了
// setw(4)设置宽度为4,右对齐,空格补缺
template <class T>
void Grid<T>::print() {
	iterator it = begin();
	for (int a = 0; a < height; a++, cout << endl)
		for (int b = 0; b < width; b++)
			cout << setw(4) << *it, it++;
}
// get函数,获取某个位置的值
// 返回右移 n 次,下移 m 次之后对应的值就行 复杂度 O(W*H)
template <class T>
T Grid<T>::get(int n, int m) {
	iterator it = begin();
	while (n--)
		it.right();
	while (m--)
		it.down();
	return *it;
}
// set函数,修改某个位置的值
// 基本思路和 get 函数一样,找到位置通过迭代器的 set 函数赋值就行了
template <class T>
void Grid<T>::set(int n, int m, T val) {
	iterator it = begin();
	while (n--)
		it.right();
	while (m--)
		it.down();
	it.set(val);
}
// join函数,把另一个矩阵合并到当前矩阵右边
// 因为合并之后需要把传入的矩阵清除,所以传参用引用
template <class T>
void Grid<T>::join(Grid<T>& oth) {
	// 宽度变成合并之后的宽度
	width += oth.getWidth();
	// 修改面积
	size = width * height;
	iterator pre, back;
	// 找到当前矩阵的右上角和 oth 矩阵的左上角
	pre = begin_upper_right();
	back = oth.begin_upper_left();
	// 然后把这两个节点链接在一起,并一起向下移动,就想拉拉链一样把两个矩阵缝合起来
	while (pre != end()) {
		pre.itr->right = back.itr;
		back.itr->left = pre.itr;
		pre.down(); back.down();
	}
	// 重新设置当前矩阵的右上角和右下角的指向
	upper_right = oth.upper_right;
	lower_right = oth.lower_right;
	// 清除 oth 矩阵的信息
	oth.width = oth.height = oth.size = 0;
	oth.upper_left = oth.upper_right = nullptr;
	oth.lower_left = oth.lower_right = nullptr;
}
// stack函数,把两个矩阵上下合并
// 思路和join函数相同,代码也差不多,结合着看就行
template <class T>
void Grid<T>::stack(Grid<T>& oth) {
	height += oth.getHeight();
	size = width * height;
	iterator pre, back;
	pre = begin_upper_left();
	back = oth.begin_lower_left();
	while (pre != end()) {
		pre.itr->up = back.itr;
		back.itr->down = pre.itr;
		pre.right(); back.right();
	}
	upper_left = oth.upper_left;
	upper_right = oth.upper_right;
	oth.width = oth.height = oth.size = 0;
	oth.upper_left = oth.upper_right = nullptr;
	oth.lower_left = oth.lower_right = nullptr;
}
// clear函数,和析构函数一样,删除内存,并清除相应信息
template <class T>
void Grid<T>::clear() {
	iterator it = begin();
	node<T>*ve[10000];
	int len = 0;
	while (it != end())
		ve[len++] = it.itr, it++;
	for (int a = 0; a < len; a++)
		delete ve[a];
	width = height = size = 0;
	upper_left = upper_right = nullptr;
	lower_left = lower_right = nullptr;
}
// reset函数,用一个值覆盖矩阵
// 遍历并赋值就行了
template <class T>
void Grid<T>::reset(T val) {
	iterator it = begin();
	while (end() != it) {
		*it = val;
		it++;
	}
}
// lift上下切割函数
// 因为要把切下来的矩阵给 oth,所以传参用引用
template <class T>
void Grid<T>::lift(Grid<T>::iterator x, Grid<T>& oth) {
	// 把传入的矩阵清理掉,以免赋值后出现内存泄漏
	oth.clear();
	// 三个赋值指针
	node<T> *lf = x.itr, *rt = x.itr, *p = x.itr;
	int ind = 0;
	// p的目的是找出要切割部分的高度
	while (p->up != nullptr)
		ind++, p = p->up;
	// lf的目的是找到传入迭代器的最左端
	while (lf->left != nullptr)
		lf = lf->left;
	// rt的目的是找到传入迭代器的最右端
	while (rt->right != nullptr)
		rt = rt->right;
	// 更新切下矩阵的相关信息
	oth.width = width;
	oth.height = ind;
	oth.size = oth.width*oth.height;
	// 当切下的部分至少有一行才需要更新
	if (ind != 0) {
		// 更新 oth 矩阵的四角指针
		oth.upper_left = upper_left; oth.upper_right = upper_right;
		oth.lower_left = lf->up; oth.lower_right = rt->up;
		// 因为上面被切了,所以当前矩阵的左上右上指针要下移到找到的左端点和右端点
		upper_left = lf; upper_right = rt;
		// 更新当前矩阵相关信息
		height -= ind;
		size = height * width;
		// 因为矩阵切开了,所以要把上下两部分矩阵之前的连线断开
		// 挨个断开,并不断右移
		while (lf != nullptr)
			lf->up->down = nullptr, lf->up = nullptr, lf = lf->right;
	}
}
// chop左右切割函数
// 大体思路和lift一样只是把横着的变成了竖着的,除此之外只有一个地方不同
template <class T>
void Grid<T>::chop(Grid<T>::iterator x, Grid<T>& oth) {
	oth.clear();
	node<T> *tp = x.itr, *dn = x.itr, *p = x.itr;
	int ind = 1;
	while (p->right != nullptr)
		ind++, p = p->right;
	while (tp->up != nullptr)
		tp = tp->up;
	while (dn->down != nullptr)
		dn = dn->down;
	oth.width = ind;
	oth.height = height;
	oth.size = oth.width*oth.height;
	// 因为这个切割有可能把当前矩阵切得一点不剩,所以当这种情况发生的时候,之前把 oth 赋值为当前矩阵,并把当前矩阵的信息清除就行了
	if (ind == width) {
		oth.lower_left = lower_left; oth.lower_right = lower_right;
		oth.upper_left = upper_left; oth.upper_right = upper_right;
		lower_left = lower_right = nullptr;
		upper_left = upper_right = nullptr;
		height = width = size = 0;
	}
	else {
		oth.upper_left = tp; oth.upper_right = upper_right;
		oth.lower_left = dn; oth.lower_right = lower_right;
		upper_right = tp->left; lower_right = dn->left;
		width -= ind;
		size = height * width;
		while (tp != nullptr)
			tp->left->right = nullptr, tp->left = nullptr, tp = tp->down;
	}
}

main.cpp

// =====================================================================
// =====================================================================
// NOTE: DO NOT EDIT THIS FILE EXCEPT WHERE INDICATED
// =====================================================================
// =====================================================================


#include <iostream>
#include <cassert>
#include <cstdlib>
#include <string>


// You will write the grid.h file to implement the Grid class and
// helper classes GridIterator and Node.
#include "grid.h"


// prototypes for helper testing functions
void test_example();
void test_iterators();
void test_separation();
void test_iterators_part_2();

void additional_student_tests();


// =====================================================================
// =====================================================================

int main(int argc, char* argv[]) {
  //_CrtSetBreakAlloc(361);
  // =======================================================================
  // NOTE: UNCOMMENT THESE FUNCTIONS AS YOU WORK THROUGH YOUR IMPLEMENTATION
  // =======================================================================

  test_example();
  test_iterators();
  test_separation();
  test_iterators_part_2();

  //additional_student_tests();
  _CrtDumpMemoryLeaks();
}

// =====================================================================
// =====================================================================

void test_example() {
  std::cout << "=====================================================================" << std::endl;
  std::cout << "test_example()" << std::endl;


  // ------------------------------
  // simple construction & printing
  std::cout << "\nA 5x1 horizontal row:" << std::endl;
  Grid<int> horizontal(5,1,42);
  horizontal.print();

  std::cout << "\nA 1x3 vertical column:" << std::endl;
  Grid<int> vertical(1,3,99);
  vertical.print();
  
  std::cout << "\nA 4x3 grid of zeros:" << std::endl;
  Grid<int> grid(4,3);
  assert (grid.getWidth() == 4);
  assert (grid.getHeight() == 3);
  assert (grid.getSize() == 12);
  grid.print();

  
  
  // --------------------------------------------
  // initializing and checking values by index
  // (rather inefficient for this data structure)
  std::cout << "\nNow let's initialize the grid values:" << std::endl;
  int tmp = 1;
  for (int j = 0; j < 3; j++) {
    for (int i = 0; i < 4; i++) {
      grid.set(i,j,tmp);
      tmp++;
    }
  }
  grid.print();
  assert (grid.get(0,0) == 1);
  assert (grid.get(0,1) == 5);
  assert (grid.get(2,2) == 11);

  
  // ----------------------
  // create basic iterators
  Grid<int>::iterator itr;
  itr = grid.begin_upper_left();
  assert (*itr == 1);
  itr  = grid.begin_upper_right();
  assert (*itr == 4);
  itr = grid.begin_lower_left();
  assert (*itr == 9);
  itr  = grid.begin_lower_right();
  assert (*itr == 12);
  
  
  // -------------------------------
  // combining grids: join and stack
  std::cout << "\nLet's join the vertical column on the right: " << std::endl;
  grid.join(vertical);
  assert (grid.getWidth() == 5);
  assert (grid.getHeight() == 3);
  assert (vertical.getWidth() == 0);
  assert (vertical.getHeight() == 0);
  grid.print();
  std::cout << "\nAnd stack the horizontal row on the top: " << std::endl;
  grid.stack(horizontal);
  assert (grid.getWidth() == 5);
  assert (grid.getHeight() == 4);
  assert (horizontal.getWidth() == 0);
  assert (horizontal.getHeight() == 0);
  grid.print();

  std::cout << "\ndone with test_example()" << std::endl;
}

// =====================================================================
// =====================================================================

void test_iterators() {

  
  std::cout << "=====================================================================" << std::endl;
  std::cout << "test_iterators()" << std::endl;
  
  std::cout << "\nA 6x4 grid of dots:" << std::endl;
  Grid<char> grid(6,4,'.');
  assert (grid.getWidth() == 6);
  assert (grid.getHeight() == 4);
  grid.print();

  std::cout << "\nUse an iterator to walk along a specific path in the grid:" << std::endl;
  Grid<char>::iterator itr  = grid.begin_lower_right();
  assert (*itr == '.');
  *itr = '0';
  itr.left();  *itr = '1';
  itr.up();    *itr = '2';
  itr.up();    *itr = '3';
  itr.left();  *itr = '4';
  itr.left();  *itr = '5';
  itr.left();  *itr = '6';
  itr.down();  *itr = '7';
  itr.right(); *itr = '8';
  itr.down();  *itr = '9';
  grid.print();

  
  std::cout << "\nReset all values in the grid to a specific value" << std::endl;
  grid.reset('?');
  grid.print();
  
  std::cout << "\nLabel by snaking horizontally through the grid:" << std::endl;
  char tmp = 'a';
  itr = grid.begin_snake();
  while (itr != grid.end_snake()) {
    assert (*itr == '?');
    *itr = tmp;
    tmp++;
    itr++;
  }
  grid.print();

  grid.clear();
  assert (grid.getSize() == 0);
  assert (grid.getWidth() == 0);
  assert (grid.getHeight() == 0);
    
  std::cout << "\ndone with test_iterators()" << std::endl;
 
}

// =====================================================================
// =====================================================================

void test_separation() {
  
  std::cout << "=====================================================================" << std::endl;
  std::cout << "test_separation()" << std::endl;

  std::cout << "\nPrepare an interesting grid:" << std::endl;
  Grid<int> grid(7,5);
  int tmp = 1;
  Grid<int>::iterator itr = grid.begin_snake();
  while (itr != grid.end_snake()) {
    assert (*itr == 0);
    *itr = tmp;
    tmp++;
    itr++;
  }
  grid.print();
  itr = grid.begin_upper_left();
  itr.right().right().down().down();
  assert (*itr == 17);

  
  std::cout << "\nLifting off the top:" << std::endl;
  Grid<int> top;
  assert (top.getSize() == 0 && top.getWidth() == 0 && top.getHeight() == 0);
  grid.lift(itr,top);
  top.print();

  std::cout << "\nLeaving the rest:" << std::endl;
  grid.print();
  assert (*itr == 17);

  
  std::cout << "\nChopping off the right:" << std::endl;
  Grid<int> side;
  grid.chop(itr,side);
  side.print();

  std::cout << "\nLeaving the rest:" << std::endl;
  grid.print();
  assert (*itr == 17);
  itr.right().down();
  assert (*itr == 25);

  
  std::cout << "\nJoin it back together on the other side:" << std::endl;
  side.join(grid);
  side.print();

  std::cout << "\nAnd stack on the top:" << std::endl;
  top.stack(side);
  top.print();
  assert (top.getWidth() == 7);
  assert (top.getHeight() == 5);
  assert (top.getSize() == 35);

  assert (*top.begin_upper_left()  == 17);
  assert (*top.begin_upper_right() == 16);
  assert (*top.begin_lower_right() == 8);
  assert (*top.begin_lower_left()  == 14);
  
  std::cout << "\ndone with test_separation()" << std::endl;
  
}

// =====================================================================
// =====================================================================

void test_iterators_part_2() {
  
  std::cout << "=====================================================================" << std::endl;
  std::cout << "test_iterators_part_2()" << std::endl;

  std::cout << "\nA 6x4 grid of _'s:" << std::endl;
  Grid<char> grid(6,4,'_');  
  grid.print();

  std::cout << "\nLabel by spiraling into the grid:" << std::endl;
  char tmp = 'A';
  Grid<char>::iterator itr = grid.begin_spiral();
  while (itr != grid.end_spiral()) {
    assert (*itr == '_');
    *itr = tmp;
    tmp++;
    itr++;
  }
  grid.print();


  std::cout << "\nAnd a larger example:" << std::endl;
  Grid<int> bigger(8,10,0);
  Grid<int>::iterator itr2 = bigger.begin_spiral();
  int tmp2 = 1;
  while (itr2 != bigger.end_spiral()) {
    *itr2 = tmp2;
    tmp2++;
    itr2++;
  }
  bigger.print();


  // walking off the board should hit the end iterator
  itr2 = bigger.begin_lower_left();
  assert (*itr2 == 24);
  itr2.right().right();
  assert (*itr2 == 22);
  itr2.down();
  assert (itr2 == bigger.end()); 

  itr2 = bigger.begin_upper_right();
  assert (*itr2 == 8);
  itr2.down().down();
  assert (*itr2 == 10);
  itr2.right();
  assert (itr2 == bigger.end());

  
  std::cout << "\nA dereferenced iterator can be an l-value (and modify data):" << std::endl;
  itr2 = bigger.begin_lower_right();
  itr2.up().left().up().left();
  assert (*itr2 = 65);
  *itr2 = 0;
  assert (bigger.get(5,7) == 0);

  itr2 = bigger.begin_snake();
  for (int i = 0; i < 19; i++) { itr2++; }
  assert (*itr2 = 58);
  *itr2 = -1;
  assert (bigger.get(3,2) == -1);
  
  bigger.print();
  
  std::cout << "\ndone with test_iterators_part_2()" << std::endl;
  
}  


// =====================================================================
// =====================================================================

void additional_student_tests() {

  std::cout << "=====================================================================" << std::endl;
  std::cout << "additional_student_tests()" << std::endl;



  // =======================================================================
  // NOTE: WRITE YOUR OWN TEST CASES HERE!
  // =======================================================================



  std::cout << "done with additional_student_tests()" << std::endl;
}

// ======================================================================
// ======================================================================

 

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值