抽象思维&OOP面对对象程序设计 by徐明星老师

抽象思维:提取共性,应对变化

用于做程序设计维护、应用。。抽象:认识和表达世界

对比算法,发现共性

对比下楼问题和跳马问题

下楼问题与跳马问题 见https://blog.csdn.net/weixin_43829465/article/details/96004805
在这里插入图片描述
两个问题的差异:1、是否达到目标;2、新位置的计算(高度、落点坐标);3、判断是否合法

#include<iostream>
using namespace std;

/// task-dependent
struct position{ int x,y; };
position dxy[] ={{}{}{}{}}


//通用算法框架
void Jump(){
	if(IsDone(pos)){
		num++;
		cout<<
	}
}


通过辅助函数将共同点寻找出来,将差异思维隔离开来。
通过修改task-dependent相关的模块,适用于两种问题。

转换视角、提取共性

任务2.2 对比分书问题与八皇后问题

分书问题与八皇后问题见https://blog.csdn.net/weixin_43829465/article/details/96004805
在这里插入图片描述
类似于八皇后。
分书问题中,一本书只能给一个人、一个人只能选一本书。转化为二维矩阵。
均有共同的限定条件:每一行、每一列只能出现一次,不重不漏。不能出现第二个皇后、把书分配出去的标记。
不同点:八皇后对角线不能重;分书问题非全二维矩阵、是矩阵的子集
利用限定的条件去设置矩阵元素。

这两个问题的代码重构

#include<iostream>
using namespace std;

// #define QUEEN 
//增加了条件编译选项

bool IsValid(){

}



int main(){
	num = 0;
	place_state state = CreateInitState();
	Try(0,state);
	
	return 0;
}

思考题:下楼、跳马、分书、八皇后四个问题能否合成同一个抽象的算法框架??

代码重构、隔离变化

任务2.3 填充数字旋转方阵

逆时针旋转矩阵(1~NN)填充nn矩阵

函数Fill(number,begin,size)从位置(begin,begin)开始填写。矩阵大小为size*size。

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

int m[m][n] = {{0}};

void Show()
{
	for(int i = 0)
}

任务2.4基于OOP来解决矩阵填充

Object Oriented Programming(OOP)面向对象程序设计

int main() \\main函数测试代码、一般先看先写main代码
{
	matrix obj;
	cout<<"please input N:";
	int size;
	cin >> size;

	obj.init(size); 
	obj.fill();
	obj.print();
	obj.clear();
	
	return 0;
}

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

class matrix 
{
	int N;
	int** M;//用二维指针代表矩阵
	int row,col;
	char dir;		 //'D''R''U''L'

	void place(int num);

public:
	void init(int size);
	void clear();

	void fill();
	void print();
}

void matrix::init(int size)
{
	N = size;
	
	col = 0; raw = -1;
	dir = 'D';		//最初方向

	M = new int*[N];
	for (int r=0; r<N; r++) //r代表每一列
	{
		M[r] = new int[N];
		memset(M[r], 0, sizeof(int)*N ); //矩阵清零、表示无数字
	}
}

void matrix::clear()
{
	for(int r=0; r<N; r++) delete[] M[r];
	delete[] M;
}


void matrix::place(int num)
{
	//step1:先根据前一位置、方向,以及摆放规则(DRUL)确定下一个摆放数据的位置
	switch(dir)
	{	
		//以下为部分源代码
		case 'D':
			// 先保证row在合法范围内,再考虑该处是否有数字(为零?)
			if (row < N-1 && M[row+1][col] == 0)
				row++;
			else{
				dir = 'R';
				col++;
			}
			break;
	}
}

思考题:逆时针填充变为顺时针?若均要支持?若要支持蛇形、Z字形、U字形呢?
很少改动去应对复杂变化->如何用最高的效率去面对变化。(抽象)

任务2.5深入思考:矩阵到底是什么?

M为矩阵的数学运算接口
F为旋转填充的操作接口
矩阵的数学本质:结构化的多维数据
填充操作不是矩阵所固有的、填充操作可以独立于矩阵。

#ifndef MATRIX_H
#define MATRIX_H

#include<iostream>
using namespace std;

class matrix
{
	int row,col,**buf; \\数据区域buf--指针的指针
public:
	matrix(int,int);
	~matrix();

	int& operator() (int r,int c); //matrix_obj(r,c)   取一个值出来,返回一个引用 对矩阵的第r行第c列进行赋值。将值附到obj中。
	friend ostream& operator << (ostream&, const matrix&);  //运算符重载输出结果
} ;
#endif


#include "matrix.h"

#include<iostream> 	//cout
#include<iomanip>	//setw()
using namespace std;

matrix::matrix(int r, int c)
	: row(r), col(c)
{
	buf = new int*[row];
	for (int i = 0; i<row; i++)
		buf[i] = new int[col];
}

matrix::~matrix()
{
	for(int i=0; i<row; i++)
		delete[] buf[i];
	delete buf;
}

// 用函数运算符(),实现对矩阵多下标访问支持
int& matrix::operator() (int r, int c)
{
	return buf[r][c];
} 

ostream& operator << (ostream& o, const matrix& m)
{
	for(int i=0; i<m.row; i++)
	{
		for(int j=0; j<m.col; j++)
			o << setw(2) << m.buf[i][j] << ' ';
		o << endl;
	}
	return o;
}

#ifdef TEST_MATRIX //条件编译:ifdef 判断某个宏定义是否被定义,若已定义则执行随后语句 下面是matrix类的测试代码
int main()
{
	matrix m(4,5);
	for(int i=0; i<4; i++)
		for(int j=0; j<5; j++ )
			m(i, j) = i*j;
	cout << "Matrix 4X5:" << endl;
	cout << m << endl;

	return 0;
}
#endif

// g++ -DTEST_MATRIX matrix.cpp

任务2.6 深入思考:填充算法是什么?

在这里插入图片描述
F:当前位置、当前方向、新位置、规则(下一方向)
输入是他需要、输出是他要得到的——抽象
填充算法的本质-按指定规则,依次生成位置信息。
不同规则的共性如何抽取?如何描述?
用不同的字母表示不同移动方向(大写字母连续前进多步、小写字母前进一步)
Z向右上,z向左下;D down向下 ;R right向右 ;U up向上 ;L left向左
逆时针旋转:DRUL
顺时针旋转:RDLU
U字型:DrUr(竖)、RdLd(横)
Z字型:dZrz…、rzdZ…
设定了字母的集合、每个字母有特定的含义。根据需要选择相应的文字
即根据字符串内容逐个解析字符串、逐个步骤操作。

#ifdef FILLER_H
#define FILLER_H
struct location{ int row, col; };
class filler{
	location pos ;
	char rule[4];
	int idx; //填充方向 dir =rule[idx]
	
	int row_num, col_num;
	int r_min, r_max, c_min, c_max; //用于实现旋转方阵

public:
	filler(int, int); //range

	void reset();
	void set_rule(const char*);

	location operator *();    //get current location
	filler operator ++ (int); // post ++ ,next location
};
#endif

#include "filler.h"
#include "cstring"
using namespace std;

filler :: filler(int rn, int cn)
	: row_num(rn), col_num(cn) { reset(); }

void filler::reset(){
	pos.row = pos.col = 0;
	idx = 0;
	r_min = c_min = 0;
	r_max = row_num - 1 ;
	c_max = col_num - 1 ; 
}

void filler::set_rule(const char* r)
{	strncpy(rule,r,4);	}

location filler::operator* ()
{	return pos;	}


借鉴思考1–标准模板库STL

容器(数据结构)、算法、迭代器(运用算法)。

任务2.7深入思考:规则是什么?

规则在本质上是独立于填充算法而存在的。
在这里插入图片描述
class rule 设计思路
(f,r)-> " 字符串 "
指令怎么存的相对于filler对象是封闭的
参照STL将规则给剥离出去

思考题:如果被填充的是迷宫,要求根据制定规则,生成从入口到出口的路径。如何抽象共性?

借鉴思考2–正则表达式

由字符组成的序列、能与之按规则(定义)匹配的字符串的集合。从某种角度看正则表达式也是一种语言.
由字母所组成的字符串,互相进行匹配。
有一些特殊的字符称为元字符
例如 ^ 表示字符串开始 $表示字符串结束
printf()格式化字符串其会按给定的字符串输出数据。

任务2.8 正则表达式工具grep简版

函数grep扫描每一个文件、对每一行采用grep函数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值