1. 程式人生 > >使用棧實現可配置的括號對齊以及棧的實現原理

使用棧實現可配置的括號對齊以及棧的實現原理

丟擲問題:校驗字串中括號是否對應,並可以根據配置修改需要匹配的成對字元。

例:()()(())  OK

()[]{}{([])}  OK

((())]  NO

對應則返回true,若不對應則返回false

C#程式碼如下(與java程式碼差距不大),使用棧(新進後出,和裝羽毛球的盒子一樣)這種方式來處理此種問題,程式碼簡潔易懂不做過多陳述:

public class Question
{
        // _dictionary以右括號為key, 左括號為值
        private Dictionary<char, char> _dictionary = null;

        public Question()
        {
            //可對匹配字串進行配置修改
            _dictionary = new Dictionary<char, char>
            {
                { ')', '(' },
                { '}', '{' },
                { ']', '[' }
            };
        }

        public  bool IsMatch(string str)
        {
            Stack<char> sc = new Stack<char>();
            for (int i = 0; i < str.Length; i++)
            {
                char ch = str[i];
                if (_dictionary.ContainsValue(ch))// 如果是左括號,放入棧中
                {
                    //壓入棧
                    sc.Push(ch);
                }
                else if (_dictionary.ContainsKey(ch)) // 如果是右括號
                {
                    if (sc.Count == 0) // 棧為空,棧頭沒有字元與右括號匹配
                    {
                        return false;
                    }
                    // 棧不為空,棧頭字元與右括號匹配
                    if (sc.Peek() == _dictionary[ch])
                    {
                        //出棧
                        sc.Pop();
                    }
                    else
                    {
                        return false;
                    }
                }
            }
            return sc.Count == 0 ? true : false;
        }
    }

接下來看一下棧的原始碼部分了解一下其實現原理:

        private T[] _array;     // Storage for stack elements
        private int _size;           // Number of items in the stack.
        private int _version;        // Used to keep enumerator in sync w/ collection.

其實棧內就一個泛型的陣列來儲存我們壓進去的值,只有通過_size來壓入新的值或者取出存入的值

push:

        // Pushes an item to the top of the stack.
        // 
        /// <include file='doc\Stack.uex' path='docs/doc[@for="Stack.Push"]/*' />
        public void Push(T item) {
            if (_size == _array.Length) {
                T[] newArray = new T[(_array.Length == 0) ? _defaultCapacity : 2*_array.Length];
                Array.Copy(_array, 0, newArray, 0, _size);
                _array = newArray;
            }
            _array[_size++] = item;
            _version++;
        }

因為陣列在宣告的時候必須限定大小,所以會有一個預設的大小,當新的值壓入進來後會進行判斷大小是否可存入陣列,如果無法儲存則會擴充套件陣列後在將值存入。

pop:

        // Pops an item from the top of the stack.  If the stack is empty, Pop
        // throws an InvalidOperationException.
        /// <include file='doc\Stack.uex' path='docs/doc[@for="Stack.Pop"]/*' />
        public T Pop() {
            if (_size == 0)
                ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EmptyStack);
            _version++;
            T item = _array[--_size];
            _array[_size] = default(T);     // Free memory quicker.
            return item;
        }

出棧首先判斷棧中是否存在資料。之後通過_size來控制出棧的值。

因為棧需要新進後出,所以不存在使用下標獲取值或賦值的方式。

就我個人而言 Java的原始碼要比C#的原始碼看起來更整齊,更好理解。

記錄生活點點滴滴。

版權宣告:本文為博主原創文章,未經博主允許不得轉載。