2019-12-26 10:02:24 qq_40629521 阅读数 9
  • 数据结构实战完全手册

    数据结构是程序设计的必修知识,它是程序设计的基本功,并且在企业面试、日常工作、研究生入学考试中都占有重要的地位。不同于其他课程,本课程从单链表出发,手把手的全代码实现了栈与队列,树、图(包括数组和链表的两种形式),并对这些经典结构的应用也做了代码级的实现,覆盖了经典数据结构的全部内容. 课程参考教材:周幸妮教授的《数据结构与算法分析新视角》 由德古意特(DE GRUYTER. 德国)和科学出版社联合出版 对应英文版《Data Structures and Algorithms Analysis – New Perspectives》

    1224 人正在学习 去看看 夏曹俊

Day07 数据结构

定时器 —线程

public class Test01 {
	public static void main(String[] args) {
		//新建一个定时器
		
		Timer t = new Timer();
		
		t.schedule(new Boom(), 3000,1000);
	}
}
class Boom extends TimerTask{
	public void boom() {
	}

	@Override
	public void run() {
		System.out.println("bommbommbomm....");
		
	}
}

数据结构的认识

什么是数据结构

组织存储数据的一种方式

常见的数据结构:

  • 链表
  • 数组
  • 队列
  • 散列表

自定义容器

  1. 能够存储一种类型,指定长度的的容器
    • 1.具有添加能力
      • 先定义一个数组 用来存储数据
      • 增加一个方法给底层的数组添加数据
        • 定义一个计数器(成员变量) 每添加一条数据 计数器就+1
  2. 数组的打印问题
    把底层的数组里面的默认数据也打印出来了,用户 体验差
    • 覆写toString();
      • 新声明一个临时数组,长度为size
      • 把底层arr里面的有效数据拷贝到临时数组中
      • 对外使用Arrays输出临时数组里面的结果
  3. 长度的问题,底层数组长度固定
    • 添加数据的时候,容器是否够用
      • 有空余容器—》直接添加数据
      • 把以前的数据拷贝到新的数组中
      • 把即将添加的数据放到新的数据中
      • 把新的数组的地址值给底层的arr
  4. 存储的数据类型问题
    • 把底层用于存储数据的数组改为Object类型
  5. 对容器里面的功能扩充(CRUD)
    • 删除
      • 删除指定位置的数据
      • 根据值删除值
    • 查询
      • 返回指定索引位置的数据
      • 查询指定数据第一次出现的索引位置
    • 修改
      • 根据索引修改
      • 根据值修改
public class MyArrayList {
	
	private Object[] arr;
	
	//无参的的构造方法给定数组固定的长度
	public MyArrayList() {
		this(10);
	}
	
	//有参的构造方法给数组用户输入的长度
	public MyArrayList(int i) {
		arr = new Object[i];
	}
	
	//计数器
	private int size;
	//添加方法
	public void add(Object i) {
		
		
		//如果添加数据的长度超过了数组长度
		if (size == arr.length) {
			Object[] temp = new Object[size+5];
			System.arraycopy(arr, 0, temp, 0, size);
			arr = temp;
		}else {
			arr[size++] = i;
		}
	}
	
	//根据索引修改值
	public void updateByIndex(int i,Object o) {
		if (i < 0 || i > size-1) {
			throw new ArrayIndexOutOfBoundsException("你的索引无效 请输入[0~"+(size-1)+"]之间的数");
		}else {
			arr[i] = o;
		}
	}
	
	//修改查找到所有的值
	public void uapdateByObjAll(Object o,Object obj) {
		for (int i = 0; i < size; i++) {
			if (o.equals(arr[i])) {
				arr[i] = obj;
			}
		}
	}
	
	//修改第一个查找到的值
	public void uapdateByObj(Object o,Object obj) {
		for (int i = 0; i < size; i++) {
			if (o.equals(arr[i])) {
				arr[i] = obj;
				break;
			}
		}
	}

	//根据索引删除值
	public void removeByIndex(int i) {
		if (i < 0 || i > size-1) {
			throw new ArrayIndexOutOfBoundsException("你的索引无效 请输入[0~"+(size-1)+"]之间的数");
		}
		System.arraycopy(arr, i+1, arr, i, arr.length-i-1);
		size--;
	}

	//根据值删除数组里的值
	public void delByObj(Object o) {
//		removeByIndex(getIndex);
		for (int i = 0; i < size; i++) {
			if (o.equals(arr[i])) {
				System.arraycopy(arr, i+1, arr, i, arr.length-i-1);
				size--;
				break;
			}
		}
	}
	
	//根据索引查找值
	public Object getObjByIndex(int i) {
		if (i < 0 || i > size-1) {
			throw new ArrayIndexOutOfBoundsException("当前索引没有值  请输入[0~"+(size-1)+"]之间的数");
		}
		return arr[i];
	}
	
	//根据值查找位置
	public int getIndexByObj(Object o) {
		for (int i = 0; i < size; i++) {
			if (o.equals(arr[i])) {
				return i+1;
			}
		}
		return -1;
	}
	
	//返回数组的长度
	public int size() {
		return size;
	}
	
	@Override
	public String toString() {
		
		Object[] temp = new Object[size];
		System.arraycopy(arr, 0, temp, 0, size);
		
		String string = Arrays.toString(temp);
		
		return string;
	}
}

2018-07-29 16:39:22 likunkun__ 阅读数 677
  • 数据结构实战完全手册

    数据结构是程序设计的必修知识,它是程序设计的基本功,并且在企业面试、日常工作、研究生入学考试中都占有重要的地位。不同于其他课程,本课程从单链表出发,手把手的全代码实现了栈与队列,树、图(包括数组和链表的两种形式),并对这些经典结构的应用也做了代码级的实现,覆盖了经典数据结构的全部内容. 课程参考教材:周幸妮教授的《数据结构与算法分析新视角》 由德古意特(DE GRUYTER. 德国)和科学出版社联合出版 对应英文版《Data Structures and Algorithms Analysis – New Perspectives》

    1224 人正在学习 去看看 夏曹俊

数据结构(java篇):

内容要求:这一部分需要自己先去学习一遍数据结构,然后自己写出来。掌握之后,再去查看api文档,最后学会如何使用api里的数据结构写算法。下面介绍的主要是每个数据结构与api的对应方式。此文为初级算法总结的子篇第三章——数据结构。

1、基础数组、线性表:

(1)数组:

Java数组的定义:int[] arr = new int[n];

                   或者int[] arr = new int[]{1,2,3};

                  Int arr = { 1,2,3 };

API:Arrays提供二分法查找、比较、复制、填充某个数(fill)、排序、返回字符串等功能。具体功能查询Arrays。

(2)线性表:

API:ArrayList中提供加入(add),删除(remove),重置(set),返回索引(indexof),裁剪(sublist)具体功能查询API帮助文档。

2、链表:

自己实现参照:数据结构(java)——单链表、双端链表和双向链表

链表是以节点类为基础的,每个节点类有一个成员变量是下一个节点。

API:LinkedList提供添加删除获取索引元素等操作,具体查看api帮助文档。

3、集合:

API:Collections接口提供:排序,二分查找,逆序,随机打乱,填充,copy,max,min,比较,指定元素出现次数等操作。用法直接collections.max(链表或者数组)。

这个接口提供了很多常用方法,具体如何使用可以参照帮助文档。

4、向量:

API:Vector接口提供方法与数组类似,具体查看API帮助手册。

5、栈:

自己实现参照:数据结构(java)——栈和队列

API:Stack接口提供查看,移除,压入,查找,判空操作

6、队列、双端队列、优先队列:

(1)队列:数据结构(java)——栈和队列

API:Queue接口在LinkedList类上加入了查看队头,移除队头,加入元素等特殊操作。用LinkedList类来实例化队列。

(2)双端队列:

API:Deque接口提供双端的插入删除操作,具体查看api。同样用LinkedList类来实例化。

(3)优先队列:

API:PriorityQueue类实现了以自然顺序排列的队列(注意 不是先排序再出,而是出队的时候选择最小的先出)。可默认比 较器(最小的有最高优先度),也可用其他比较器,如 Collections.reverseOrder()提供的逆序比较器进行优先出队。具 体怎么用查看api帮助文档。

7、哈希表(映射表):

API:

(1)Hashmap提供了键—值对应的功能,keyset返回包含键的视图(可用来foreach遍历),values返回包含值的视图,还有put,remove,size,isempty,get,containkey(value)等常规操作。

(2)TreeMap提供了可排序的映射表,构造方法可以加入比较器comparator。entrySet返回键视图,values返回值视图。

8、树:

树没有api,可以用上面学过的东西去实现它,参照:数据结构(java)——二叉树的插入、遍历、删除、高度、叶子节点个数、判完全二叉树等操作

如何构造树包括以下几点:

(1)节点:数据域,左右孩子,是否背访问等信息;

(2)(二叉查找树)插入节点:第一次插入直接,直接插到root; 然后比较大小循环左右走,newNode > now就插右边,否则插 左边。

(3)二叉树拷贝:递归,拷贝root,左子树,右子树。

(4)查找节点:和插入一样

(5)前中后序遍历:递归(跟-左子树-右子树or等等),非递归(利用栈,先压root,然后对顶元素根据前中后遍历方式决定先看左/右/跟,如果是孩子就压入,是跟就弹出)。

(6)层序遍历:用队列,先压root,弹一个就压他的左右进去。

(7)中序后继节点:某节点的右孩子的一直左孩子下去的节点。方法是定义3个节点,del和delp(del的父节点,最开始也指向del)和now(del的right),然后delp = del;del = now;now=now.left;一直到now为空,del就是中序后继节点。

(8)删除节点:

        1.删叶子:分左右直接。

        2.删有一个孩子的节点:分是左孩子还是右孩子,还要 分删除的节点是左还是右。

        3.删除有两个孩子的节点,找中序后继节点替换。中序 后继节点应该在找的时候吧下面的连接处理好。

(9)求k层节点的个数:递归左子树的第k-1层+右子树k-1层。

(10)叶子节点个数:递归,左子树的叶子+右叶子。

(11)树高度:max:左子树高度+1 or 右子树高度+1。

(12)检测完全二叉树:层序遍历,在某个节点(没有双子或右孩子)后全是叶子节点

9、图:

图也是没有api的,用之前学过的结构可以构造。

如何构造图包括以下几点,详见:

(1)顶点类:名称,值,是否背访问。

(2)图类:顶点数组、邻接矩阵、栈、队列、最大顶点

(3)添加点和边:加进顶点数组和邻接矩阵

(4)获取相邻顶点:遍历邻接矩阵的那一行,==1返回.

(5)深度优先搜索DFS:利用栈,访问标记压入0号,看栈顶得到周边,访问标记并压入,没有了能访问的就弹出。搜索完吧访问记录删除。

(6)广度优先BFS:用队列,访问标记压入0号,循环找不到周边就弹出,找得到就访问标记并压入。

 

2018-04-10 11:16:09 qq2512667 阅读数 737
  • 数据结构实战完全手册

    数据结构是程序设计的必修知识,它是程序设计的基本功,并且在企业面试、日常工作、研究生入学考试中都占有重要的地位。不同于其他课程,本课程从单链表出发,手把手的全代码实现了栈与队列,树、图(包括数组和链表的两种形式),并对这些经典结构的应用也做了代码级的实现,覆盖了经典数据结构的全部内容. 课程参考教材:周幸妮教授的《数据结构与算法分析新视角》 由德古意特(DE GRUYTER. 德国)和科学出版社联合出版 对应英文版《Data Structures and Algorithms Analysis – New Perspectives》

    1224 人正在学习 去看看 夏曹俊

Array 数组

在c#语言中,数组是最简单的数据结构,具有以下3个特点  

(1) 数组储存在连续的内存上;

(2)数组的元素都是相同类型或者类型的衍生类型,因此数组又被认为是同质数据结构

(3)数组可以直接通过下标访问。array[i]来访问;

 常规操作:

(1)分配储存空间, 声明一个新的数组 int[]arr=new int[5];

(2) 访问数组中的元素数据,通过下标获取某个元素;int i= arr[0];

Mono运行时的托管堆中分配一块连续的内存空间盛放数量为size,连续内存上储存,索引快,两个元素插入之间便不方便;


Arraylist数组

不必声明数组长度,可以储存不同类型元素,

每个元素为obj来处理;(不安全) 插入值类型会发生装箱操作,索引取值时会发生拆箱操作;


list<T>

工作时常用,和Arraylist相似,在声明list集合时,需要指定内部数据的存储类型,

List<string> test =new List<string>();

test.Add("abc");

test[0]="def";

test.RemoveAt(0);

确保类型安全, 类型安全;

取消装箱拆箱 高性能;

可以快速访问,灵活变化


LinedList<T>

链表

U3D中 已经封装好了

LinkedList<T> 链表类 双向列表 Next  Previous

LinkedListNode<T> 链表节点

AddFirst 将一个新节点加入该链表的第一个节点位置;

AddLast 将一个新节点加入该链表的最后一个节点位置;

AddBefore 在某个节点前插入新节点

AddAfter 在某个节点后插入新节点;

RemoveFirst 移除第一个节点;

RemoveLast 移除最后一个节点;

Remove 移除指定节点;


队列 &栈

队列,特殊的线性表,(FIFO)先进先出, 像是在超市买菜排队结账;3

初始容量为32

允许在前端 head删除, 而在后端 tail 进行插入 

插入操作,队尾, 删除操作,队头

c# U3D Queue<T>

Queue<string> number = new Queue<string>();
 number.Enqueue("one");//插入操作
 number.Enqueue("Two");

 number.Dequeue(); //删除操作

 栈 又名堆栈

形象一点就是 把东西堆起来, 先堆进去的最后出来。是也(LIFO)后进先出;

c# U3D Stack<T>

一样是运算受限制的线性表 仅允许在表的一端进行插入 删除运算,栈顶, 栈底,

插入叫进栈 入栈 压栈,把新元素放到栈顶,删除元素 称 出栈 退栈,把顶元素删除,

Stack<T>类有个 push 和pop方法;

peek//  看顶部元素, 偷看。。。

  Stack<string> number2 = new Stack<string>();

.peek//  看顶部元素, 偷看。。。

number2.Push("abc"); //入栈

 number2.Push("efg"); //出栈

 number2.Pop(); //此时删除的是efg、

number2.peek//  看顶部元素, 偷看。。。

count总数,    如果Stack<T>中元素数量count小于其容量,Push操作时间复杂度为O(1);

如果容量需要被扩展,根据需要来重新分配内部数组以自动增大容量,这种情况下Push操作复杂度为O(n),出栈操作Pop操作复杂度为O(1);

Hash Table(哈希表) Dictionary<K,T> 字典

键值对

哈希表 散列表

根据关键码/值(key/value)直接进行访问的数据结构,通过关键码/值映射到表中的一个位置来访问记录,加快查找速度;

C#提供两种机制

冲突避免机制

冲突解决机制

冲突解决策略为开放寻址法

最简单的实现一种就是 线性探查,3个步骤

1 插入新元素时, 使用哈希函数在哈希表中定位元素位置。

2 检查哈希表中该位置是否已经存在元素。如果该位置内容为空,插入并返回,否认执行3

3 如果该位置为i,则检查i+1是否为空,如果已被占用,而检查i+2。依次类推,直到找到为空。

会导致同类哈希的聚集

改进方式为二次探查

每次检查位置空间的步长为平凡倍数,如果位置s被占用,而首先检查s+12处,然后检查 s-12 s+22 s-22 s+32 s-32......

但同样也会导致同类哈希聚集问题

Hashtable herosDic = new Hashtable();

        herosDic.Add("111-11-1234", "Hero1");
        herosDic.Add("111-12-1234", "Hero2");
        herosDic.Add("111-13-1237", "Hero3");
        herosDic.Add("111-14-1235", "Hero4");
        herosDic.Add("111-15-1235", "Hero5");


        if (herosDic.ContainsKey("111-11-1234"))
        {
            string heroName = (string)herosDic["111-11-1234"];
            Debug.Log("ID111-11-1234" + heroName);
        }
        else {
            Debug.Log("111-11-1234不存在");
        }

ContainsKey

ContainsValue

remove(key)

来源 小黄书

Dictionary<K,T> 字典

 Dictionary<string, int> student = new Dictionary<string, int>();

        student.Add("xiaoming", 0);
        student.Add("xiaohong", 1);
        student.Add("xiaobing", 2);

        foreach (var itme in student) {
            Debug.Log("val"+itme.Value + "key"+itme.Key);
        }
        student.Remove("xiaoming");
        //缺点就是耗 内存空间 慎用



2020-01-09 18:17:06 songyilianblog 阅读数 30
  • 数据结构实战完全手册

    数据结构是程序设计的必修知识,它是程序设计的基本功,并且在企业面试、日常工作、研究生入学考试中都占有重要的地位。不同于其他课程,本课程从单链表出发,手把手的全代码实现了栈与队列,树、图(包括数组和链表的两种形式),并对这些经典结构的应用也做了代码级的实现,覆盖了经典数据结构的全部内容. 课程参考教材:周幸妮教授的《数据结构与算法分析新视角》 由德古意特(DE GRUYTER. 德国)和科学出版社联合出版 对应英文版《Data Structures and Algorithms Analysis – New Perspectives》

    1224 人正在学习 去看看 夏曹俊

数据结构中数据存储的几种形式

1.栈:数据从一个口进,从一个口出
特点:先入后出
2.队列:数据用两个口进,从两个口出
特点:先入先出
3.数组:
特点:查找容易,增删难
例子:
int [] arr = new int [1,2,3,4];
当创建数组的时候,对于1,2,3,4已经创建索引,并且将首地址赋予arr,要是查找,就很快;对于增删操作,当要是删除原本的数组里面的某一个数据,首先就需要重新建一个数组,然后将删除数据后的数组里面的数据复制后粘贴到新建的数组里面,这个过程就比较耗时;
新建一个数组的原因:数组创建之后数组的长度是不变的,当进行增删操作的时候,数组的长度就变化了,源数组就不适用了,这时就需要一个新的数组来存放操作后的数据。

4.链表:
特点:查找复杂,增删容易
有关于链表:单独的数据存在的形式:
单独数据的存在形式
两种链表的形式:单项链表和双向链表
单向链表:
只能向一个方向 ,不具有记忆性
双向链表:
具有记忆性,可以知道上一个数据源是什么

有关于链表查找复杂的讲解:在链表之中的数据不是像数组那样数据时连续的,在链表之中,数据是离散的,所以每次查找数据会就需要从头开始查询,这样就比较复杂并且耗时

增删的容易性:应为单独数据存在的形式,增删数据就只需要修改一下下一个数据的数据源地址就可以了

5.树:
有关于树的一些基本概念:
树根,节点,树叶
树根:树最上面的节点 也叫作父根
节点:连接着树根与树叶的点,就叫做节点
树叶:除了上面的一个节点,下面不存在节点

二叉树:
分支不能超过两个,可以说是左子树(左边)与右子树(右边)
完全二叉树(平衡二叉树):所有的节点都含有两个儿子(左子树与右子树)
不完全二叉树:并不是说所有的节点都有两个儿子
排序树/查找树:
排序树特点:小于的数就往左,大于的数就往右
红黑树:
特点:趋近于平衡树,查询速度特别快,查询叶子结点的最大次数和最小次数不能超过两倍
有关于红黑树的约束:
a.节点可以是红色的也可以是黑色的
b.根节点是黑色的
c.叶子结点(空节点)是黑色的
d.每个红色的节点的子节点都是黑色的
e.任何一个节点到其每一个叶子节点的所有路径上的黑色节点数相同

2015-05-17 17:16:41 u013030441 阅读数 1010
  • 数据结构实战完全手册

    数据结构是程序设计的必修知识,它是程序设计的基本功,并且在企业面试、日常工作、研究生入学考试中都占有重要的地位。不同于其他课程,本课程从单链表出发,手把手的全代码实现了栈与队列,树、图(包括数组和链表的两种形式),并对这些经典结构的应用也做了代码级的实现,覆盖了经典数据结构的全部内容. 课程参考教材:周幸妮教授的《数据结构与算法分析新视角》 由德古意特(DE GRUYTER. 德国)和科学出版社联合出版 对应英文版《Data Structures and Algorithms Analysis – New Perspectives》

    1224 人正在学习 去看看 夏曹俊

    通过组合结构和指针可以创建强大的数据结构。该博客只是针对了单链表来看的。

链表说明:

    链表的每一个结点都是一个结构体,其中有两个元素分别是:1、指向下一个结点的指针(link)和该结点数据(value)。其中需要一个根指针指向第一个结点(root)。

插入数据:

  初始代码:

    插入的思想是通过比较当前结构的数据和要插入的数据(new_value)大小,从而判断插入位置。首先需要定义两个指针变量,一个指向当前结构(current),一个指向当前结构的前一个结构(previous)。当判断好位置之后需要做的就是分配一个新结点(new),同时将结点插入。

代码如下:

#include <stdlib.h>
#include <stdio.h>
#include "sll_node.h"

#define FALSE 0
#define TRUE  1

int 
sll_insert( Node *current, int new_value )
{
	Node *previous;
	Node *new;

	/*
	**寻找正确的插入位置,方法是按顺序访问链表,直到到达其值大于或等于
	**新插入的节点值。
	*/
	while( current->value < new_value )
	{
		previous = current;
		current = current->link;
	}

	/*
	**为新节点分配内存,并把新值存储到新结点中,如果内存分配失败,
	**函数返回FALSE。
	*/
	new = (Node *)malloc( sizeof( Node ));
	if( new == NULL )
		return FALSE;
	new->value = new_value;

	/*
	**把新节点插入到链表中,并返回TRUE。
	*/
	new->link = current;
	previous->link = new;
	return TRUE;

}

  调试升级:

    但是其中存在如下问题:1、在判断插入位置的过程中,要判断是否已经访问到最后一个结点,如果不做此判断在循环指针赋值的过程中由于current为空指针会造成间接访问失败。2、如果在链表第一个位置插入结点就需要改变根指针,因此就需要定义个指向根指针的指针(rootp),通过对根指针的指针来对对根节点进行操作。对比上一个代码有如下代码:

#include <stdlib.h>
#include <stdio.h>
#include "sll_node.h"

#define FALSE 0
#define TRUE  1

int 
sll_insert( Node **rootp, int new_value )
{
	Node *current;
	Node *previous;
	Node *new;

	/*
	**得到指向第一个结点的指针。
	*/
	current = *rootp;
	previous = NULL;

	/*
	**寻找正确的插入位置,方法是按顺序访问链表,直到到达其值大于或等于
	**新插入的节点值。
	*/
	while( current != NULL && current->value < new_value )
	{
		previous = current;
		current = current->link;
	}

	/*
	**为新节点分配内存,并把新值存储到新结点中,如果内存分配失败,
	**函数返回FALSE。
	*/
	new = (Node *)malloc( sizeof( Node ));
	if( new == NULL )
		return FALSE;
	new->value = new_value;

	/*
	**把新节点插入到链表中,并返回TRUE。
	*/
	new->link = current;
	if( previous == NULL )
		*rootp = new;
	else
		previous->link = new;
	return TRUE;

}

  优化升级:

    好像调试升级以后就已经很好了,但是其实还可以再进行优化升级,优化升级的思想就是排除起始位置的特殊情况,抓住其中的共性来进行操作。链表的共性就是每一个结点都有一个指向它的指针。第一个结点的指针是根指针(root),其他结点的指针是上一个结点的指针元素(link)。因此在这里定义一个指针(linkp),这个指针可以指向一个字段,该字段是指向下一个结点的指针;最初该指针指向根指针,即指向第一个结点的指针。还需要一个指向当前结点的指针(current)。如此一来我们便将关注中心从结点到了指向下一个结点的指针。对比上边代码如下:

#include <stdlib.h>
#include <stdio.h>
#include "sll_node.h"

#define FALSE 0
#define TRUE  1

int 
sll_insert( register Node **linkp, int new_value )
{
	register Node *current;
	register Node *new;

	/*
	**寻找正确的插入位置,方法是按顺序访问链表,直到到达其值大于或等于
	**新插入的节点值。
	*/
	while((current = *linkp) != NULL && current->value < new_value )
	{
		linkp = ¤t->link;
	}

	/*
	**为新节点分配内存,并把新值存储到新结点中,如果内存分配失败,
	**函数返回FALSE。
	*/
	new = (Node *)malloc( sizeof( Node ));
	if( new == NULL )
		return FALSE;
	new->value = new_value;

	/*
	**把新节点插入到链表中,并返回TRUE。
	*/
	new->link = current;
	*linkp = new;
	return TRUE;

}

总结认识:

    从这三步的优化中第二步是对第一步的错误进行处理的过程,第三步是对第二步的操作优化,优化的思想是从看上去不同的操作中去总结共性,即抽象,找到共性后就可以用一项操作完成多个看似不同的任务,其实我们一直在做这些东西,不仅从知识中找共性,从生活中也可以找共性,从生活的现象中抽象出来的就是规律,其实规律还可以再做进一步的抽象,一步步向上抽象就可以发现一些最根本的规律和真理,然后我们就可以依据这些规律和真理去注重我们日常的一些具体的行为和举动,从而帮助我们处理好一些问题。

lua的数据结构

阅读数 7280

动态数据结构

阅读数 3845

Set和Map数据结构

阅读数 507

没有更多推荐了,返回首页