天天看點

渣渣寫算法之隊列

渣渣寫算法之隊列

隊列 Queue

隊列可以用數組和連結清單來實作

考慮到隊列的移除時數組資料的調整,分成了幾個情況

①移動數組,這樣當然來講,是性能不咋好的,通過一個指針并移動整體位置來實作,從一個角度解決了由于出對導緻非環形的數組中無用項的問題

public class ArrayQueue<T>
    {
        public int Length
        {
            get
            {
                return curIndex + 1;
            }
        }
        private int maxSize = 100;

        private int curIndex = -1;

        private T[] _data = null;

        public ArrayQueue()
        {
            _data = new T[maxSize];
        }

        public void Clear()
        {
            curIndex = -1;
        }


        public void EnQueue(T item)
        {
            curIndex++;
            if (curIndex >= maxSize)
            {
                Console.WriteLine("隊列已滿");
                return;
            }
            _data[curIndex] = item;
        }



        public T DeQueue()
        {
            if (curIndex > -1)
            {
                var data = _data[0];
                if (curIndex > 0)
                {
                    for (int i = 1; i <= curIndex; i++)
                    {
                        _data[i - 1] = _data[i];
                    }
                }
                curIndex--;
                return data;
            }
            throw new Exception("No Elem");
            return default(T);
        }

    }
      

  ②環形數組實作1,利用倆指針配合來完成數組的利用,用count統計控制目前有效的個數

public class CircleArrayQueue<T>
    {
        private int maxSize = 100;
        private int firstIndex = -1;
        private int lastIndex = -1;
        private T[] _data = null;

        public CircleArrayQueue(int setMaxSize = 4)
        {
            maxSize = setMaxSize;
            _data = new T[maxSize];
        }

        private bool isFull()
        {
           return Length== maxSize;
        }

        private bool isEmpty()
        {
            return Length==0;
        }

        public void Clear()
        {
            firstIndex = lastIndex = -1;
            Length = 0;
        }

        public int Length { get; private set; } = 0;



        public void EnQueue(T item)
        {
            if (isFull())
            {
                Console.WriteLine("已滿");
                return;
            }
            Length++;
            lastIndex++;
            if (lastIndex >= maxSize)
            {
                lastIndex = 0;
            }
            _data[lastIndex] = item;
            if (firstIndex == -1)
            {
                firstIndex = 0;
            }
        }



        public T DeQueue()
        {
            if (isEmpty())
            {
                throw new Exception("沒有元素");
            }
            Length--;
            var data = _data[firstIndex];
            firstIndex++;
            if (firstIndex >= maxSize)
            {
                firstIndex = 0;
            }
            return data;
        }

    }
      

  

③環形數組實作2,其實兩個指針也可以統計出隊列中有效項的個數,不用額外定義一個count個數

public class CircleArray2Queue<T>
    {
        private int maxSize = 100;
        private int firstIndex = -1;
        private int lastIndex = -1;
        private T[] _data = null;

        public CircleArray2Queue(int setMaxSize = 4)
        {
            maxSize = setMaxSize;
            _data = new T[maxSize];
        }

        private bool isFull()
        {
            return (lastIndex + 1) % maxSize == firstIndex;
        }

        private bool isEmpty()
        {
            return firstIndex == -1||lastIndex == firstIndex;
        }

        public int Length
        {
            get
            {
                return firstIndex == -1 ? 0 : (lastIndex + maxSize - firstIndex) % maxSize + 1;
            }
        }

        public void Clear()
        {
            firstIndex = lastIndex = -1;
        }


        public void EnQueue(T item)
        {
            if (isFull())
            {
                Console.WriteLine("已滿");
                return;
            }
            lastIndex++;
            if (lastIndex >= maxSize)
            {
                lastIndex = 0;
            }
            _data[lastIndex] = item;
            if (firstIndex == -1)
            {
                firstIndex = 0;
            }
        }



        public T DeQueue()
        {
            if (isEmpty())
            {
                throw new Exception("沒有元素");
            }
            var data = _data[firstIndex];
            if (firstIndex != lastIndex)
            {
                firstIndex++;
                if (firstIndex >= maxSize)
                {
                    firstIndex = 0;
                }
            }
            return data;
        }

    }
      

  ④ 當然 ,還可以使用單連結清單來實作,通過連結清單的指針指向下一個,來找下一個元素,出隊的時候修正連結清單指針即可

public class CircleLinkQueue<T>
    {
        private class Item
        {
            public Item Next;
            public T Data;
        }

        private Item curItem = null;

        private Item firstItem = null;

        public int Length { get; private set; } = 0;

        public void Clear()
        {
            Length = 0;
            firstItem = null;
            curItem = null;
        }

        public void EnQueue(T item)
        {
            Length++;
            var d = new Item()
            {
                Data = item
            };
            if (curItem == null)
            {
                firstItem = d;
            }
            else
            {
                curItem.Next = d;
            }
            curItem = d;
        }



        public T DeQueue()
        {
            if (Length > 0 && firstItem != null)
            {
                var dd = firstItem.Data;
                Length--;
                firstItem = firstItem.Next;
                return dd;
            }
            else
            {
                throw new Exception("No Elem");               
            }
        }
    }
      

  相比較于數組本身,數組有天然的指針結構,相鄰的元素有着天然的聯系,但是維護起來需要一定的邏輯,是以連結清單就定義了一個結構,包含了對元素本身和執行下一個元素,來友善指定聯系,連結清單中相連的元素在内部可能是不連續的。