2018年6月

 逆波兰式(Reverse Polish notation) 
using System;
using System.Collections.Generic;
using System.Text;

namespace Test1 {
    class Program {

        static bool IsNumber(string c) {
            int result = 0;
            return int.TryParse(c,out result);
        }

        static bool IsOperator(string c) {
            return c == "+" || c == "-" || c == "*" || c == "/" || c == "(" || c == ")";
        }


        static bool ComparePriority(string op1, string op2) {
            return GetPriority(op1) > GetPriority(op2);
        }

        static int GetPriority(string c) {
            int priority;
            switch (c) {
                case "+":
                    priority = 1;
                    break;
                case "-":
                    priority = 1;
                    break;
                case "*":
                    priority = 2;
                    break;
                case "/":
                    priority = 2;
                    break;
                default:
                    priority = 0;
                    break;

            }
            return priority;
        }

        static int Calculate(string op, int num1, int num2) {
            int result = -1;
            switch (op) {
                case "+":
                    result = num1 + num2;
                    break;
                case "-":
                    result = num1 - num2;
                    break;
                case "*":
                    result = num1 * num2;
                    break;
                case "/":
                    result = num1 / num2;
                    break;
            }
            return result;
        }

        static Stack<string> ChangeExpression(List<string> beforeExps) {
            Stack<string> numberStack = new Stack<string>();
            Stack<string> operatorStack = new Stack<string>();

            //遍历中序表示
            int length = beforeExps.Count;
            //判断是否为操作数  
            for (int i = 0; i < length; i++) {

                string c = beforeExps[i];
                if (IsNumber(c)) {
                    //操作数 存在操作数栈
                    numberStack.Push(c);
                } else {
                    //为运算符  
                    //若运算符为"("直接存入到运算符栈中 
                    if (c == "(") {
                        operatorStack.Push(c);
                    } else if (c == ")") {
                        //该运算符为右括号")",则输出运算符堆栈中的运算符到操作数堆栈,直到遇到左括号为止。 将"("出栈  
                        while (operatorStack.Peek() != "(") {
                            string stringvalue = operatorStack.Pop();
                            numberStack.Push(stringvalue);
                        }
                        operatorStack.Pop();
                    } else {
                        // 该运算符为非括号运算符:
                        //考虑栈顶为空的情况 
                        if (operatorStack.Count <= 0) {
                            operatorStack.Push(c);
                            continue;
                        }
                        // (a) 若运算符堆栈栈顶的运算符为括号,则直接存入运算符堆栈。
                        ////符合为左括号 直接存入运算符
                        if (operatorStack.Peek() == "(") {
                            operatorStack.Push(c);
                        } else {
                            //(b) 若比运算符堆栈栈顶的运算符优先级高或相等,则直接存入运算符堆栈。  
                            if (ComparePriority(c, operatorStack.Peek())) {
                                operatorStack.Push(c);
                            } else {
                                // (c) 若比运算符堆栈栈顶的运算符优先级低,则输出栈顶运算符到操作数堆栈,并将当前运算符压入运算符堆栈。
                                string stringvalue = operatorStack.Pop();
                                numberStack.Push(stringvalue);
                                operatorStack.Push(c);
                            }

                        }
                    }
                }
            }
            //4、当表达式读取完成后运算符堆栈中尚有运算符时,则依序取出运算符到操作数堆栈,直到运算符堆栈为空。
            while (operatorStack.Count > 0) {
                string stringvalue = operatorStack.Pop();
                numberStack.Push(stringvalue);
            }
            //反转operand 获取正常的会缀表达式
            Stack<string> resultSt = new Stack<string>();
            while (numberStack.Count > 0) {
                string stringvalue = numberStack.Pop();
                resultSt.Push(stringvalue);
            }
            return resultSt;
        }

        //转换string为list表
        static List<string> changeStrToList(string str) {
            List<string> resultSt = new List<string>();
            List<int> sortNum = new List<int>();
            bool isConNum = false;
            foreach (char c in str) {
                if (IsOperator(c.ToString())) {
                    if (isConNum && sortNum.Count > 0) {
                        //添加数字
                        int num = 0;
                        for (int i = sortNum.Count - 1; i >= 0; i--) {
                            if (i == sortNum.Count - 1) {
                                num = num + sortNum[i];
                            } else {

                                num = num + sortNum[i] * 10 * (sortNum.Count - 1 - i);
                            }

                        }
                        resultSt.Add(num.ToString());
                        sortNum.Clear();
                    }
                    isConNum = false;
                    //如果是操作符直接添加
                    resultSt.Add(c.ToString());
                } else {
                    //如果是数字
                    isConNum = true;
                    sortNum.Add(int.Parse(c.ToString()));
                }
            }
            if (sortNum.Count > 0) {
                //添加数字
                int num = 0;
                for (int i = sortNum.Count - 1; i >= 0; i--) {
                    if (i == sortNum.Count - 1) {
                        num = num + sortNum[i];
                    } else {
                        num = num + sortNum[i] * 10 * (sortNum.Count - 1 - i);
                    }
                }
                resultSt.Add(num.ToString());
                sortNum.Clear();
            }
            return resultSt;
        }
        //计算逆波兰公式
        static int calculateExpression(Stack<string> st) {
            //临时存储计算数据
            Stack<string> reslutSt = new Stack<string>();
            while (st.Count > 0) {
                string numStr = st.Peek();
                if (IsNumber(numStr)) {
                    //如果字符是一个操作数,把它压入堆栈。
                    reslutSt.Push(numStr);
                } else {
                    //如果字符是个操作符,弹出两个操作数,执行恰当操作,
                    //然后把结果压入堆栈。如果您不能够弹出两个操作数,后缀表达式的语法就不正确。 
                    int number1 = int.Parse(reslutSt.Pop());
                    int number2 = int.Parse(reslutSt.Pop());
                    int value = Calculate(numStr, number2, number1);
                    reslutSt.Push(value.ToString());
                }
                st.Pop();
            }
            return int.Parse(reslutSt.Peek());
        }
        static void Main(string[] args) {
            Console.WriteLine("C# 逆波兰公式 输入您要计算的公式,按enter结束");
            //string inputStr = Console.ReadLine();
            string teststr = Console.ReadLine();
            List<string> inputStr = changeStrToList(teststr);
            Console.WriteLine("公式为:");
            foreach (string str in inputStr) {
                Console.Write("{0} ", str);
            }
            Console.Write(" ===> ");
            Stack<string> changeSt = ChangeExpression(inputStr);
            foreach (string str in changeSt) {
                Console.Write("{0} ", str);
            }
            Console.WriteLine("逆波兰公式计算:");
            //计算公式的值
            int resultValue = calculateExpression(changeSt);
            Console.WriteLine("{0} = {1} ", teststr, resultValue);

            Console.ReadKey();
        }
    }
}
View Code

Dijkstra 双栈算术表达式

        public static Double Evaluate(string str) {
            Stack<double> values = new Stack<double>();
            Stack<Char> ops = new Stack<char>();

            char[] chs = str.ToCharArray();
            for(int i = 0; i < chs.Length; i++) {
                if(chs[i] == '+') {
                    ops.Push(chs[i]);
                }else if(chs[i] == '-') {
                    ops.Push(chs[i]);
                } else if(chs[i] == '*') {
                    ops.Push(chs[i]);
                } else if(chs[i] == '/') {
                    ops.Push(chs[i]);
                } else if(chs[i] == '(') {

                } else if(chs[i] == ')') {
                    char op = ops.Pop();

                    double value = values.Pop();
                    if(op == '+') {
                        value = value + values.Pop();
                    } else if(op == '-') {
                        value = values.Pop() - value;
                    } else if(op == '*') {
                        value = values.Pop() * value;
                    } else if(op == '/') {
                        value = values.Pop() / value;
                    }
                    values.Push(value);
                } else {
                    values.Push(double.Parse(chs[i].ToString()));
                }
            }

            return values.Pop();
        }
View Code
 

 

function baz() {
    // 当前调用栈是: baz
    // 因此,当前调用位置是全局作用域
    
    console.log("baz");
    bar();    // <-- bar的调用位置
}

function bar() {
    // 当前调用栈是baz -> bar
    // 因此,当前调用位置在baz中
    
    console.log("bar");
    foo(); // <-- foo的调用位置
}

function foo() {
    // 当前调用栈是baz -> bar -> foo
    // 因此,当前调用位置在bar中
    
    console.log("foo");
}

baz();    // <-- baz的调用位置
<script type="text/javascript">

function foo() {
    // this == window
    console.log(this.a);debugger;
}

var a = 2;

foo();

</script>

debugger;

函数this的默认绑定为全局对象,严格模式下"use strict",this默认绑定到undefined,因为全局对象无法使用默认绑定

// 无论是直接在obj中定义还是先定义再添加为引用属性,这个函数严格来说i都不属于obj对象
function foo() {
    console.log(this.a);
}

var obj = {
    a:2,
    foo:foo
};

// 调用位置会使用obj上下文来引用函数,因此你可以说函数被调用时obj对象"拥有"或者"包含"它
// 当函数引用有上下文对象时,隐式绑定规则会把函数调用中的this绑定到这个上下文对象.
// 因为调用foo()时this被绑定到obj,因此this.a和obj.a是一样的
obj.foo();
var obj = {
    a:2,
    foo:foo
};

// 虽然bar是obj.foo的一个引用,但实际上,它引用的是foo函数本身
// 因此此时的bar()其实是一个不带任何修饰的函数调用,因此应用了默认绑定
var bar = obj.foo;
var a = "oops,global";
bar();
function foo() {
    console.log(this.a);
}

function doFoo(fn) {
    // 参数传递其实就是一种隐式赋值,因此我们传入函数时也会被隐式赋值.
    // fn其实引用的是foo
    fn();
}

var obj = {
    a:2,
    foo:foo
};

var a = "oops,global";
doFoo(obj.foo);
function foo() {
    console.log(this.a);
}

var obj = {
    a:2,
    foo:foo
};

var a = "oops,global";
setTimeout(obj.foo, 100);

// pseudo setTimeout
function setTimeout(fn,delay) {
    fn();
}
function foo(something) {
    console.log(this.a,something);
    return this.a + something;
}

var obj = {
    a:2
};

// bind(..)会返回一个硬编码的新函数,它会把参数设置为this的上下文并调用原始函数
var bar = foo.bind(obj);
var b = bar(3);
console.log(b);
function foo(a) {
    this.a = a;
}

// 实际上并不存在所谓的"构造函数",只有对于函数的"构造调用"
// 使用new来调用foo(..)时,我们会构造一个新对象并把它绑定到foo(..)调用中的this上.
// new是最后一种可以影响函数调用时this绑定行为的方法,我们称之为new绑定
var bar = new foo(2);
console.log(bar.a);
function foo() {
    console.log(this.a);
}

var obj1 = {
    a:2,
    foo:foo
};

var obj2 = {
    a:3,
    foo:foo
};

obj1.foo();
obj2.foo();

// 显式绑定优先级更高
obj1.foo.call(obj2);
obj2.foo.call(obj1);
function foo(something) {
    this.a = something;
}

var obj1 = {
    foo:foo
};

var obj2 = {}

obj1.foo(2);
console.log(obj1.a);    // 2

obj1.foo.call(obj2,3);
console.log(obj2.a);    // 3

var bar = new obj1.foo(4);
console.log(obj1.a);    // 2
console.log(bar.a);     // 4
function foo(something) {
    this.a = something;
}

var obj1 = {
    foo:foo
};

var obj2 = {}

obj1.foo(2);
console.log(obj1.a);    // 2

obj1.foo.call(obj2,3);
console.log(obj2.a);    // 3

var bar = new obj1.foo(4);
console.log(obj1.a);    // 2
console.log(bar.a);     // 4    new绑定比隐式绑定优先级高
function foo(something) {
    this.a = something;
}

var obj1 = {}

var bar = foo.bind(obj1);
bar(2);
console.log(obj1.a);    // 2

var baz = new bar(3);
console.log(obj1.a);    // 2
console.log(baz.a);     // 3
// 判断this
// 1. 函数是否在new中调用(new绑定)?如果是的话this绑定的是新创建的对象
var bar = new foo();
// 2. 函数是否通过call,apply(显式绑定)或者硬绑定调用?如果是的话,this绑定的是指定的对象
var bar = foo.call(obj2);
// 3. 函数是否在某个上下文对象中调用(隐式绑定)?如果是的话,this绑定的是那个上下文对象.
var bar = obj1.foo();
// 4. 如果都不是的话,使用默认绑定.如果在严格模式下,就绑定到undefined,否则绑定到全局对象
var bar = foo()
// ES6中的箭头函数并不会使用四条标准的绑定规则,而是根据当前的词法作用域来决定this,
// 具体来说,箭头函数会继承外层函数调用的this绑定(无论this绑定到什么).
// 这其实和ES6之前代码中的self=this机制一样
function foo() {
    // 返回一个箭头函数
    return (a) => {
        // this 继承自foo()
        console.log(this.a);
    };
}

var obj1 = {
    a:2
};

var obj2 = {
    a:3
};

// foo()内部创建的箭头函数会捕获调用时foo()的this.
// 由于foo()的this绑定到obj1,bar(引用箭头函数)的this也会绑定到obj1,
// 箭头函数的绑定无法被修改(new也不行!)
var bar = foo.call(obj1);
bar.call(obj2); // 2
// 简单基本类型
console.log(typeof "a");        // string
console.log(typeof 1);          // number
console.log(typeof true);       // boolean
console.log(typeof null);       // object 语言本身的bug
console.log(typeof undefined);  // undefined
console.log(typeof {});         // object

// javascript中有许多特殊的对象子类型,我们可以称之为复杂基本类型
函数
数组

// 内置对象,实际上只是一些内置函数,这些函数可以当作构造函数来使用,
String
Number
Boolean
Object
Function
Array
Date
RegExp
Error

var strPrimitive = "I am a string";
console.log(typeof strPrimitive);   // "string"
console.log(strPrimitive instanceof String);  // false

var strObject = new String("I am a string");
console.log(typeof strObject);  // "object"
console.log(strObject instanceof String);   // true

// 检查 sub-type 对象
console.log(Object.prototype.toString.call(strObject)); // [object String]
var myObject = {
    a:2
};

console.log(myObject.a);     // 属性访问
console.log(myObject["a"]);  // 键访问

// 在对象中,属性名永远都是字符串.如果你使用string(字面量)以外的其他值作为属性名,那它首先会被转换为一个字符串
var myObject1 = {};
myObject1[true] = "foo";
myObject1[3] = "bar";
myObject1[myObject1] = "baz";

console.log(myObject1["true"]); // "foo"
console.log(myObject1["3"]);    // "bar"
console.log(myObject1["[object Object]"]);  // "baz"
// 可计算属性名
var prefix = "foo";
var myObject = {
    [prefix + "bar"]:"hello",
    [prefix + "baz"]:"world"
};

console.log(myObject["foobar"]);
console.log(myObject["foobaz"]);

GO

 

原文地址:https://www.cnblogs.com/revoid/p/9124601.html