OSDN Git Service

微修正
authorkomutan <t_komuta@nifty.com>
Sun, 12 Jul 2015 09:16:03 +0000 (18:16 +0900)
committerkomutan <t_komuta@nifty.com>
Sun, 12 Jul 2015 09:16:03 +0000 (18:16 +0900)
src/LibNMeCab/Core/PriorityQueue.cs
src/LibNMeCabTest/PriorityQueueTest.cs

index 9f8a489..fd8f7db 100644 (file)
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace NMeCab.Core
-{
-    public class PriorityQueue<T>
-        where T : IComparable<T>
-    {
-        private class HeapNode
-        {
-            public T Value { get; private set; }
-            public int ChildsCount { get; private set; }
-            public HeapNode FirstChild { get; private set; }
-            public HeapNode LastChild { get; private set; }
-            public HeapNode Prev { get; private set; }
-            public HeapNode Next { get; private set; }
-
-            public void AddFirstChild(HeapNode first)
-            {
-                this.ChildsCount++;
-                if (this.ChildsCount == 1)
-                {
-                    this.LastChild = first;
-                }
-                else
-                {
-                    HeapNode old = this.FirstChild;
-                    first.Next = old;
-                    old.Prev = first;
-                }
-                this.FirstChild = first;
-            }
-
-            public void AddLastChild(HeapNode last)
-            {
-                this.ChildsCount++;
-                if (this.ChildsCount == 1)
-                {
-                    this.FirstChild = last;
-                }
-                else
-                {
-                    HeapNode old = this.LastChild;
-                    last.Prev = old;
-                    old.Next = last;
-                }
-                this.LastChild = last;
-            }
-
-            public HeapNode PollFirstChild()
-            {
-                this.ChildsCount--;
-                if (this.ChildsCount == 0)
-                {
-                    this.LastChild.Prev = null;
-                    this.LastChild = null;
-                }
-                HeapNode first = this.FirstChild;
-                this.FirstChild = first.Next;
-                first.Next = null;
-                return first;
-            }
-
-            public HeapNode(T value)
-            {
-                this.Value = value;
-            }
-        }
-
-        private HeapNode rootNode;
-
-        public int Count { get; private set; }
-
-        public void Clear()
-        {
-            this.Count = 0;
-            this.rootNode = null;
-        }
-
-        public void Push(T item)
-        {
-            this.Count++;
-            this.rootNode = this.Merge(this.rootNode, new HeapNode(item));
-        }
-
-        public T Peek()
-        {
-            return this.rootNode.Value;
-        }
-
-        public T Pop()
-        {
-            T ret = this.Peek();
-            this.RemoveFirst();
-            return ret;
-        }
-
-        public void RemoveFirst()
-        {
-            this.Count--;
-            this.rootNode = this.UnifyChilds(this.rootNode);
-        }
-
-        private HeapNode Merge(HeapNode l, HeapNode r)
-        {
-            if (l == null) return r;
-            if (r == null) return l;
-
-            if (l.Value.CompareTo(r.Value) > 0)
-            {
-                r.AddFirstChild(l);
-                return r;
-            }
-            else
-            {
-                l.AddLastChild(r);
-                return l;
-            }
-        }
-
-        private HeapNode UnifyChilds(HeapNode node)
-        {
-            HeapNode[] tmp = new HeapNode[node.ChildsCount / 2]; //必要な要素数が明らかなのでStackではなく配列
-
-            for (int i = 0; i < tmp.Length; i++)
-            {
-                HeapNode x = node.PollFirstChild();
-                HeapNode y = node.PollFirstChild();
-                tmp[i] = this.Merge(x, y);
-            }
-
-            HeapNode z;
-            if (node.ChildsCount == 1) //子要素数が奇数の場合、まだ1つ残っている子要素をここで処理
-                z = node.PollFirstChild();
-            else
-                z = null;
-
-            for (int i = tmp.Length - 1; i >= 0; i--) //逆順ループで配列をStackのように振る舞わせる
-            {
-                z = this.Merge(tmp[i], z);
-            }
-
-            return z;
-        }
-    }
-}
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+\r
+namespace NMeCab.Core\r
+{\r
+    /// <summary>\r
+    /// 優先度付き先入れ先出しコレクション(実装アルゴリズムはPairing Heap)\r
+    /// </summary>\r
+    /// <typeparam name="T"></typeparam>\r
+    public class PriorityQueue<T>\r
+        where T : IComparable<T>\r
+    {\r
+        private class HeapNode\r
+        {\r
+            public T Value { get; private set; }\r
+            public int ChildsCount { get; private set; }\r
+            private HeapNode firstChild;\r
+            private HeapNode lastChild;\r
+            private HeapNode next;\r
+\r
+            public void AddFirstChild(HeapNode newNode)\r
+            {\r
+                this.ChildsCount++;\r
+                if (this.ChildsCount == 1)\r
+                    this.lastChild = newNode;\r
+                else\r
+                    newNode.next = this.firstChild;\r
+                this.firstChild = newNode;\r
+            }\r
+\r
+            public void AddLastChild(HeapNode newNode)\r
+            {\r
+                this.ChildsCount++;\r
+                if (this.ChildsCount == 1)\r
+                    this.firstChild = newNode;\r
+                else\r
+                    this.lastChild.next = newNode;\r
+                this.lastChild = newNode;\r
+            }\r
+\r
+            public HeapNode PollFirstChild()\r
+            {\r
+                HeapNode ret = this.firstChild;\r
+                this.ChildsCount--;\r
+                if (this.ChildsCount == 0)\r
+                {\r
+                    this.firstChild = null;\r
+                    this.lastChild = null;\r
+                }\r
+                else\r
+                {\r
+                    this.firstChild = ret.next;\r
+                    ret.next = null;\r
+                }\r
+                return ret;\r
+            }\r
+\r
+            public HeapNode(T value)\r
+            {\r
+                this.Value = value;\r
+            }\r
+        }\r
+\r
+        private HeapNode rootNode;\r
+\r
+        public int Count { get; private set; }\r
+\r
+        public void Clear()\r
+        {\r
+            this.Count = 0;\r
+            this.rootNode = null;\r
+        }\r
+\r
+        public void Push(T item)\r
+        {\r
+            this.Count++;\r
+            this.rootNode = this.MergeNodes(this.rootNode, new HeapNode(item));\r
+        }\r
+\r
+        public T Pop()\r
+        {\r
+            if (this.Count == 0) throw new InvalidOperationException("Empty");\r
+\r
+            this.Count--;\r
+            T ret = this.rootNode.Value;\r
+            this.rootNode = this.UnifyChildNodes(this.rootNode);\r
+            return ret;\r
+        }\r
+\r
+        private HeapNode MergeNodes(HeapNode l, HeapNode r)\r
+        {\r
+            if (l == null) return r;\r
+            if (r == null) return l;\r
+\r
+            if (l.Value.CompareTo(r.Value) > 0)\r
+            {\r
+                r.AddFirstChild(l);\r
+                return r;\r
+            }\r
+            else\r
+            {\r
+                l.AddLastChild(r);\r
+                return l;\r
+            }\r
+        }\r
+\r
+        private HeapNode UnifyChildNodes(HeapNode node)\r
+        {\r
+            HeapNode[] tmp = new HeapNode[node.ChildsCount / 2]; //必要な要素数が明らかなのでStackではなく配列\r
+\r
+            for (int i = 0; i < tmp.Length; i++)\r
+            {\r
+                HeapNode x = node.PollFirstChild();\r
+                HeapNode y = node.PollFirstChild();\r
+                tmp[i] = this.MergeNodes(x, y);\r
+            }\r
+\r
+            HeapNode z;\r
+            if (node.ChildsCount == 1) //子要素数が奇数の場合、まだ1つ残っている子要素をここで処理\r
+                z = node.PollFirstChild();\r
+            else\r
+                z = null;\r
+\r
+            for (int i = tmp.Length - 1; i >= 0; i--) //逆順ループで配列をStackのように振る舞わせる\r
+            {\r
+                z = this.MergeNodes(tmp[i], z);\r
+            }\r
+\r
+            return z;\r
+        }\r
+    }\r
+}\r
index c21acad..48b1731 100644 (file)
-using System;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using System.Collections.Generic;
-using System.Linq;
-using System.Diagnostics;
-
-namespace LibNMeCabTest
-{
-    public class Element : IComparable<Element>
-    {
-        public int Priority { get; set; }
-
-        public int Order { get; set; }
-
-        public int CompareTo(Element other)
-        {
-            return this.Priority.CompareTo(other.Priority);
-        }
-
-        public override int GetHashCode()
-        {
-            return this.Priority;
-        }
-
-        public override bool Equals(object obj)
-        {
-            var other = obj as Element;
-            return other != null
-                && this.Priority == other.Priority
-                && this.Order == other.Order;
-        }
-
-        public override string ToString()
-        {
-            return "priority:" + this.Priority + " order:" + this.Order;
-        }
-    }
-
-    [TestClass]
-    public class PriorityQueueTest
-    {
-        [TestMethod]
-        public void TestMethod1()
-        {
-            var queue = new NMeCab.Core.PriorityQueue<Element>();
-            var collection = new List<Element>();
-            var count = 0;
-
-            for (int i = 0; i < 5; i++)
-            {
-                //追加 優先度昇順
-                for (int j = 0; j < 5; j++)
-                {
-                    var item = new Element { Priority = j, Order = count };
-                    queue.Push(item);
-                    collection.Add(item);
-                    count++;
-                    Assert.AreEqual(queue.Count, count);
-                }
-            }
-
-            //並べ直し
-            collection = (from e in collection
-                          orderby e.Priority, e.Order
-                          select e).ToList();
-
-            //取り出し
-            foreach (var expected in collection)
-            {
-                var actual = queue.Pop();
-                count--;
-
-                Assert.AreEqual(expected, actual);
-                Assert.AreEqual(count, queue.Count);
-            }
-        }
-
-        [TestMethod]
-        public void TestMethod2()
-        {
-            var queue = new NMeCab.Core.PriorityQueue<Element>();
-            var collection = new List<Element>();
-            var count = 0;
-
-            for (int i = 0; i < 5; i++)
-            {
-                //追加 優先度降順
-                for (int j = 5; j >= 0; j--)
-                {
-                    var item = new Element { Priority = j, Order = count };
-                    queue.Push(item);
-                    collection.Add(item);
-                    count++;
-
-                    Assert.AreEqual(count, queue.Count);
-                }
-            }
-
-            //並べ直し
-            collection = (from e in collection
-                          orderby e.Priority, e.Order
-                          select e).ToList();
-
-            //取り出し
-            foreach (var expected in collection)
-            {
-                var actual = queue.Pop();
-                count--;
-
-                Assert.AreEqual(expected, actual);
-                Assert.AreEqual(count, queue.Count);
-            }
-        }
-
-        [TestMethod]
-        public void TestMethod3()
-        {
-            var queue = new NMeCab.Core.PriorityQueue<Element>();
-            var collection = new List<Element>();
-            var order = 0;
-            var count = 0;
-            var rnd = new Random();
-
-            //追加と取り出しを一定数繰り返す
-            for (int i = 0; i < 1000; i++)
-            {
-                //ランダム優先度でランダム個追加
-                int repeat = rnd.Next(10);
-                for (int j = 0; j < repeat; j++)
-                {
-                    var item = new Element { Priority = rnd.Next(10), Order = order };
-                    collection.Add(item);
-                    queue.Push(item);
-                    order++;
-                    count++;
-
-                    Assert.AreEqual(count, queue.Count);
-                }
-
-                //並べ直し
-                collection = (from e in collection
-                              orderby e.Priority, e.Order
-                              select e).ToList();
-
-                //ランダム個取り出し
-                repeat = rnd.Next(collection.Count);
-                for (int j = 0; j < repeat; j++)
-                {
-                    var actual = queue.Pop();
-                    var expected = collection[j];
-                    count--;
-
-                    Assert.AreEqual(expected, actual);
-                    Assert.AreEqual(count, queue.Count);
-                }
-                collection.RemoveRange(0, repeat);
-            }
-        }
-    }
-}
+using System;\r
+using Microsoft.VisualStudio.TestTools.UnitTesting;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Diagnostics;\r
+\r
+namespace LibNMeCabTest\r
+{\r
+    public class Element : IComparable<Element>\r
+    {\r
+        public int Priority { get; set; }\r
+\r
+        public int Order { get; set; }\r
+\r
+        public int CompareTo(Element other)\r
+        {\r
+            return this.Priority.CompareTo(other.Priority);\r
+        }\r
+\r
+        public override int GetHashCode()\r
+        {\r
+            return this.Priority;\r
+        }\r
+\r
+        public override bool Equals(object obj)\r
+        {\r
+            var other = obj as Element;\r
+            return other != null\r
+                && this.Priority == other.Priority\r
+                && this.Order == other.Order;\r
+        }\r
+\r
+        public override string ToString()\r
+        {\r
+            return "priority:" + this.Priority + " order:" + this.Order;\r
+        }\r
+    }\r
+\r
+    [TestClass]\r
+    public class PriorityQueueTest\r
+    {\r
+        [TestMethod]\r
+        public void TestMethod1()\r
+        {\r
+            var queue = new NMeCab.Core.PriorityQueue<Element>();\r
+            var collection = new List<Element>();\r
+            var count = 0;\r
+\r
+            for (int i = 0; i < 5; i++)\r
+            {\r
+                //追加 優先度昇順\r
+                for (int j = 0; j < 5; j++)\r
+                {\r
+                    var item = new Element { Priority = j, Order = count };\r
+                    queue.Push(item);\r
+                    collection.Add(item);\r
+                    count++;\r
+                    Assert.AreEqual(queue.Count, count);\r
+                }\r
+            }\r
+\r
+            //並べ直し\r
+            collection = (from e in collection\r
+                          orderby e.Priority, e.Order\r
+                          select e).ToList();\r
+\r
+            //取り出し\r
+            foreach (var expected in collection)\r
+            {\r
+                var actual = queue.Pop();\r
+                count--;\r
+\r
+                Assert.AreEqual(expected, actual);\r
+                Assert.AreEqual(count, queue.Count);\r
+            }\r
+\r
+            this.EmptyExceptionTest(queue);\r
+        }\r
+\r
+        [TestMethod]\r
+        public void TestMethod2()\r
+        {\r
+            var queue = new NMeCab.Core.PriorityQueue<Element>();\r
+            var collection = new List<Element>();\r
+            var count = 0;\r
+\r
+            for (int i = 0; i < 5; i++)\r
+            {\r
+                //追加 優先度降順\r
+                for (int j = 5; j >= 0; j--)\r
+                {\r
+                    var item = new Element { Priority = j, Order = count };\r
+                    queue.Push(item);\r
+                    collection.Add(item);\r
+                    count++;\r
+\r
+                    Assert.AreEqual(count, queue.Count);\r
+                }\r
+            }\r
+\r
+            //並べ直し\r
+            collection = (from e in collection\r
+                          orderby e.Priority, e.Order\r
+                          select e).ToList();\r
+\r
+            //取り出し\r
+            foreach (var expected in collection)\r
+            {\r
+                var actual = queue.Pop();\r
+                count--;\r
+\r
+                Assert.AreEqual(expected, actual);\r
+                Assert.AreEqual(count, queue.Count);\r
+            }\r
+\r
+            this.EmptyExceptionTest(queue);\r
+        }\r
+\r
+        [TestMethod]\r
+        public void TestMethod3()\r
+        {\r
+            var queue = new NMeCab.Core.PriorityQueue<Element>();\r
+            var collection = new List<Element>();\r
+            var order = 0;\r
+            var count = 0;\r
+            var rnd = new Random();\r
+\r
+            //追加と取り出しを一定数繰り返す\r
+            for (int i = 0; i < 1000; i++)\r
+            {\r
+                //ランダム優先度でランダム個追加\r
+                int repeat = rnd.Next(1, 10);\r
+                for (int j = 0; j < repeat; j++)\r
+                {\r
+                    var item = new Element { Priority = rnd.Next(10), Order = order };\r
+                    collection.Add(item);\r
+                    queue.Push(item);\r
+                    order++;\r
+                    count++;\r
+\r
+                    Assert.AreEqual(count, queue.Count);\r
+                }\r
+\r
+                //並べ直し\r
+                collection = (from e in collection\r
+                              orderby e.Priority, e.Order\r
+                              select e).ToList();\r
+\r
+                //ランダム個取り出し\r
+                repeat = rnd.Next(1, collection.Count);\r
+                for (int j = 0; j < repeat; j++)\r
+                {\r
+                    var actual = queue.Pop();\r
+                    var expected = collection[j];\r
+                    count--;\r
+\r
+                    Assert.AreEqual(expected, actual);\r
+                    Assert.AreEqual(count, queue.Count);\r
+                }\r
+                collection.RemoveRange(0, repeat);\r
+            }\r
+\r
+            while (queue.Count > 0) queue.Pop(); //空にする\r
+            this.EmptyExceptionTest(queue);\r
+        }\r
+\r
+        [TestMethod]\r
+        public void TestMethod4()\r
+        {\r
+            var queue = new NMeCab.Core.PriorityQueue<string>();\r
+\r
+            for (int i = 0; i < 10; i++) queue.Push("abc");\r
+\r
+            queue.Clear(); //テスト\r
+\r
+            Assert.AreEqual(0, queue.Count);\r
+            this.EmptyExceptionTest(queue);\r
+        }\r
+\r
+        [TestMethod]\r
+        public void TestMethod5()\r
+        {\r
+            var queue = new NMeCab.Core.PriorityQueue<int>();\r
+\r
+            //10万件挿入\r
+            for (int i = 0; i < 100000; i++) queue.Push(i % 5);\r
+\r
+            //取り出し\r
+            while (queue.Count > 0) queue.Pop();\r
+        }\r
+\r
+        private void EmptyExceptionTest<T>(NMeCab.Core.PriorityQueue<T> queue)\r
+            where T : IComparable<T>\r
+        {\r
+            try\r
+            {\r
+                queue.Pop();//空なら例外発生\r
+            }\r
+            catch (InvalidOperationException)\r
+            {\r
+                return;\r
+            }\r
+            Assert.Fail("Not Throwed Empty Exception");\r
+        }\r
+    }\r
+}\r