• 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

     

  • 相关阅读:
    python pop()
    二年为限,看到自己的改变
    Android layout布局属性、标签属性总结大全
    js判断PC端和移动端
    JS简易模拟滚动条
    (响应式PC端媒体查询)电脑屏幕分辨率尺寸大全
    手机尺寸和平板电脑的屏幕分辨率
    【整理笔记】手机端html页面制作需要了解的东西集合
    JS获取浏览器版本号及获取IE版本提示并关闭
    CSS DIV垂直居中
  • 原文地址:https://www.cnblogs.com/revoid/p/9124601.html
Copyright © 2020-2023  润新知