算法
二叉搜索树中第K小的元素
给定一个二叉搜索树,编写一个函数 kthSmallest 来查找其中第 k 个最小的元素。
说明: 你可以假设 k 总是有效的,1 ≤ k ≤ 二叉搜索树元素个数。
示例 1:
输入: root = [3,1,4,null,2], k = 1
3
/ \
1 4
\
2
输出: 1
function sortArr(arr, num){
for(let i=0; i<arr.length; i++){
if(arr[i] > num){
arr.splice(i, 0, num);
return
}
}
arr.push(num);
}
var kthSmallest = function(root, k) {
if(!root) return null;
var arr = [];
var stack = [];
stack.push(root)
while(stack.length){
var node = stack.pop();
sortArr(arr, node.val);
if(node.left) stack.push(node.left);
if(node.right) stack.push(node.right);
}
return arr.slice(k-1, k);
};
shaders 解析
着色器对象:着色器对象管理一个顶点着色器或一个片元着色器,每一个着色器都有一个着色器对象
程序对象:程序对象是管理着色器对象的容器。WebGL 中,一个程序对象必须包含一个顶点着色器和一个片元着色器
运行过程
- 创建着色器对象
- 向着色器对象中填充着色器程序的源代码
- 编译着色器
- 创建程序对象
- 为程序对象分配着色器
- 连接程序对象
- 使用程序对象
创建着色器对象
通过 gl.createShader() 函数创建着色器,type:gl.VERTEX_SHADER(顶点着色器) 和 gl.FRAGMENT_SHADER(片元着色器)
创建着色器对象之后可以通过 gl.deleteShader 对着色器对象进行删除,
制定着色器对象的代码
通过 gl.shaderSource() 函数向着色器指定 GLSL ES 源码
编译着色器
当调用 gl.compileShader() 函数时,会对着色器源码进行编译,编译完成之后可以通过 gl.getShaderParameter() 获取当前着色器编译的情况,通过 SHADER_TYPE、DELETE_STATUS、COMPILE_STATUS 获取当前着色器的类型、删除状态、编译成功与否。
如果编译失败着色器会写入信息日志,通过 gl.getShaderInfoLog() 来获取
创建程序对象
通过 gl.createProgram() 来创建程序对象。也可以通过 gl.deleteProgram(),创建了程序对象之后需要附上两个着色器
我们往着色器中传入参数的时候就是通过程序对象进行传入的。
为程序对象分配着色器对象
通过 gl.attachShader() 为程序对象分配着色器对象,WebGL 系统要运行起来必须要两个着色器,一个顶点着色器,一个片元着色器。
被分配的着色器对象不一定要是编译代码,也可以分配一个空的着色器对象。也可以通过 gl.detachShader() 进行解绑
连接程序对象
为程序对象分配着色器对象之后,还需要通过 gl.linkProgram() 对两个着色器进行链接起来,目的是保证:
- 顶点着色器和片元着色器的 varying 变量同名同类型,且一一对应;
- 顶点着色器对每个 varying 变量赋了值;
- 顶点着色器和片元着色器中的同名 uniform 变量也是同类型的。
- 着色器中的 attrbuite 变量、nuiform 变量和 varying 变量的个数没有超过着色器的上线
告知系统所使用的程序对象
通过调用 gl.useProgram() 告知 webgl 系统绘制时使用哪个程序对象
程序解析
const ininShaders = (gl, vshader, fshader) => {
var program = createProgram(gl, vshader, fshader);
...
// 告知使用的程序对象
gl.useProgram(program)
gl.program = program
return true
}
const createProgram = (gl, vshader, fshader) => {
// 创建着色器对象
var vertexShader = loadShader(gl, gl.VERTEX_SHADER, vshader);
var fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fshader);
...
// 创建程序对象
var program = gl.createProgram();
...
// 为程序对象分配着色器
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
// 连接着色器
gl.linkProgram(program);
// 检查连接
var linked = gl.getProgramParameter(program, gl.LINK_STATUS);
...
return program;
}
const loadShader = (gl, type, source) => {
// 创建着色器对象
var shader = gl.createShader(type);
...
// 设置着色器的源代码
gl.shaderSource(shader, source);
// 编译着色器
gl.compileShader(shader);
// 检查着色器的编译状态
var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
...
return shader
}