从锦囊妙计想到的28–程序的空间和时间

  categories:儿童计算机  author:

前面已经说了很多程序上的事情, 今天会引入一个程序中的两个概念, 这两个概念是非常重要的事情!

1. 程序的空间,    通常是指程序  运行时的 占用空间, 最通俗的说 就是占用内存的情况, 当然也有占用磁盘的空间的情况, 但是考虑到磁盘 空间都比较大, 不会太紧张因此, 空间通常指  内存。  另外若是您到了开发大数据的级别那么磁盘空间就要考虑了, 原因是磁盘空间会有空间同时还有访问时间的问题。

2. 程序的时间, 通常是指  程序运行时  需要的时间, 或者花费的时间。   其实后面还有一个 开发时间, 也就是开发效率的问题。  今天就不说明了。

一。 程序空间和时间的意义

举个例子, 大家都熟悉房地产了, 那么在相同面积上盖的楼越多, 最后能卖出的价格就越多, 这么就是为什么都盖高层的缘故了。

类似的, 若是 卖出的价格相同,   占用的面积越小, 越有意义是吧。

程序也是, 就是实现相同功能的情况下, 需要的内存越少, 那么整个计算机就有能力做更多的工作。

在早期的计算机 内存是k的, 有个几百个kb就很多, 后来内存多少M, 也很可怜, 现在尽管是多少G了, 但是计算机的任务也越多了, 需要的内存也越大了。

因此内存占用还是要考虑的。  但不用像以前那么斤斤计较了。

举个例子, 有两个人早上上班没吃早饭, 他们来到了一个煎饼果子面前, 甲去买了一份煎饼果子吃了,用了5元钱, 很高兴, 真便宜。 然后乙也去吃了一份一样的, 画了2元钱。 那么那个更合算?

都知道答案。

明确一下:

程序的空间 通常是指 程序运行时 占用的 内存空间

程序的时间 通常是指 程序运行时  消耗的时间

二。 使用二维数组进行缓存的内存占用情况分析

1. 如下图, 我们要输出如下图形的数据, 看看如何解决

图上图, 这个图形同前面采用二维数组作为辅助对象存储数据, 然后进行分布处理,最后输出是一样的道理

具体实现就不写了。

2. 分析一下二维数组实现的优劣

优点:   二维数组实现简单高效

缺点:  在数组非常大时, 有浪费空间的情况

声明数组如下:

char[][]   tmpBuffer = new char[12][12];

由于二维数组中每行的长度必须相同

具体情况如下:

从上图中 可以看到绿色部分的数据 是浪费的, 因此我们若是采用多个 一维数组, 没个数组长度不同, 然后在把这些一维数组串接到一起就方便了。

用上面的办法进行了多个临时缓存的设置, 那么如何把这些a1,a2, a3, a4 … 都串联到一起?

3. 用链表 连接不同的对象到一起

什么是链表? 就是用一条链把一些列的东西连接起来, 让这些东西可以从开头一个一个的找到最后的一个东西, 如下图

上图最开始是我们刚开始的a1缓冲区, 然后是a2, 然后是a3, 最后是a12

 三。java实现图形打印

1. 启动eclipse软件, 创建java项目

2. 编写相关函数

参考源代码如下:

import java.util.LinkedList;
public class MyListTuXing {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//System.out.println("采用list做临时图形输出");
		shuChuTuXing(12, 4, 7, 3);
	}
	/**
	 * 这个函数 负责输出具体的 图形
	 * @param lineCount    三角形的行数, 每一行有一个 同行数相同的*
	 */
	public static void shuChuTuXing(int lineCount, int left, int top, int line)
	{
		// 生命一个 list 对象,  用来 存储没一行的 的缓存
		LinkedList< object > tmpBuffer = new LinkedList< object >();

		// 循环 处理每一行
		for(int i = 0; i < lineCount; i++)
		{
			// 声明一个行的缓存区
			char[] tmpLineBuffer = new char[i+1];

			// 处理一行
			shuChuLineTuXing(tmpLineBuffer, i+1);

			// 把处理好的  这一行数据 添加到 链表中
			tmpBuffer.add(tmpLineBuffer);
		}

		// 这个是 输出空白图形的函数,  若是在输出 空白时, 有问题, 应该在这个函数里面
		shuChuKongBaiXing(tmpBuffer, left, top, line);

		shuAllTuXing(tmpBuffer);

	}
	/**
	 * 在已经有的缓存区中 输出一个 空白的 图形结构
	 * @param list     缓存区列表
	 * @param left     空白开始在左边第几个 位置
	 * @param top      空白开始在 上面开始的第几行
	 * @param lineCount   总计有多少行
	 */
	public static void shuChuKongBaiXing(LinkedList list, int left, int top, int lineCount)
	{
		// 循环处理  每一行
		for(int i = 0; i < lineCount; i++)
		{
			// 获取每一行的 数据
			 object  o = list.get(i + top);
			char[] tmpBuffer = (char[]) o;

			// 输出 每一行的数据
			shuChuKongBaiXingLine(tmpBuffer, left, i+1);
		}
	}
	/**
	 * 输出 每一行的  空白  图形
	 * @param tmpBuffer   临时缓存区
	 * @param left     左边开始的位置
	 * @param Line     第几行
	 */
	public static void shuChuKongBaiXingLine(char[] tmpBuffer, int left, int Line)
	{
		for(int i = 0; i < Line; i++)
		{
			tmpBuffer[left - i] = ' ';
		}
	}
	/**
	 * 输出全部的 图形信息
	 * @param list
	 */
	public static void shuAllTuXing(LinkedList list)
	{
		// 循环输出全部的数据
		for(int i = 0; i < list.size(); i++)
		{
			// 获取当前行, 数据
			 object  o = list.get(i);
			// 做强制类型转换
			char[] lineBuffer = (char[])o;
			// 在这行里面, 做循环 输出每一个  字符
			for(int j = 0; j < i + 1; j++)
			{
				// 输出每个 字符
				System.out.print(lineBuffer[j]);
			}
			// 输出换行
			System.out.println();
		}
	}

	/**
	 * 这个函数输出  每一行的  *
	 * @param buffer           行缓存
	 * @param lineXingCount    第几行, 就是这个行有几个*
	 */
	public static void shuChuLineTuXing(char[] buffer, int lineXingCount)
	{
		for(int i = 0; i < lineXingCount; i++)
		{
			buffer[i] = '*';
		}
	}

}

 

上面代码中, 通过采用     LinkedList<Object> tmpBuffer = new LinkedList<Object>();

方式声明了一个 临时缓存区 , 然后再这个缓存区里面, 把每一行的  缓存数据存储起来, 然后进行统一处理。

通过这个办法可以有效的节省 二维数组的空间浪费的问题。

【二维数组尽管浪费一些空间, 但是运行效率是很快的, 链表在运行效率上无法达到二维数组上, 这里是为了说明链表而做的特定程序, 在真正项目中要 综合考虑两个东西的特点而决定的】

3. 除了采用链表(list)来处理外, 我们还可以采用hashMap来处理

什么是map, hashmap,  其中hashmap是map的一种。 那么什么是map, 如下图

一个map可以由两部分组成 ,一部分是存放“实际东西”的部分, 通常叫做values部分

另一个部分是 存放标签的 部分  通常叫做 keys   注意两个都是复数的

在使用时, 是通过标签, 来找到 实际物体。

就像我们在查字典一样, 通过拼音或者部首找到 具体的解释在哪里。

hashmap是 map的一个具体的 实现。 具体是计算机里面的一个东西, 以后可以慢慢知道, 这里了解map就好。

那么程序中更换为map后情况如下面

HashMap<Integer, Object> tmpBuffer = new HashMap<Integer, Object>();

另外, 相关函数声明中, 需要进行处理一下, 然后就完成了修改。 功能类似 list

具体情况参考 程序的源代码,

【提示】 list 和 map 既然可以替换, 那么是否重复了!!

这里替换是在特定场景下, 离开场景就没意义了。  例如  馒头可以解饿, 猪肉也可以解饿, 那么猪肉和馒头在特定场景下可以替换, 但是当来个吃素的时候, 就只能馒头了。

list和map也是, 他们都是一个容器, 都可以存东西, 但是使用方法不一样,    list是按照 一个链接顺序来找东西的, 首先找到前面的东西, 然后在向后一个一个的找。

map是按照标签来找的, 标签可以是不连续的, 也可以是任意的。

这里之所以可以替换是因为他们 都是采用了行号的  办法来 找东西,正好前后顺序和标签 重复了。

 

程序源代码如下:28-MyList-all2

 

另外程序中出现了  LinkedList<Object>,这个是什么?

这个通俗的说 是泛型, 他的好处, 如下面图

核心就是, 通过程序使用中告诉程序, 我的容器(list, map,还有set等) 里面存储的东西的类型, 这样

开发环境就可以自动帮您检测 您放到容器里面的东西是否是这个类型, 不是这个类型的 他就抱问题, 提示你。

其实泛型技术, 不仅仅对容器有效, 还有其他的地方也有效, 具体的以后可以碰到了在说。

 

 



快乐成长 每天进步一点点      京ICP备18032580号-1