金沙国际官网_金沙国际平台登录

因为这个金沙国际官网_金沙国际平台登录网站与很多的大型澳门赌场都有合作,金沙国际官网_金沙国际平台登录尽职尽责,高效执行,保持好奇心,不断学习,追求卓越,点击进入金沙国际官网_金沙国际平台登录马上体验吧,所以现在也正式地开始了营业。

您的位置:金沙国际官网 > 编程 > net的简单封装,包括子文件夹

net的简单封装,包括子文件夹

发布时间:2019-11-03 10:36编辑:编程浏览(99)

    写在前面

    整个项目都托管在了 Github 上:

    查找更为方便的版本见:https://alg4.ikesnowy.com

    这一节内容可能会用到的库文件有 Merge,同样在 Github 上可以找到。

    善用 Ctrl + F 查找题目。

    贴代码了,这里使用的是C#控制台输出文件名到记事本中,文件名使用逗号隔开:

    分享一个以前封装的Quartz.net类。

    习题&题解

    using System;
    using System.IO;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            public static string FileName = "";
    
            public static void Main(string[] args)
            {
                bool isContinute = true;
                WriteMessage("结束程序请输入1");
                WriteMessage("请输入要获取文件名的路径:");
                string path = Console.ReadLine();
                do
                {
                    if (string.IsNullOrEmpty(path))
                    {
                        WriteMessage("路径不存在!请重新输入");
                    }
                    else
                    {
                        DirectoryInfo dir = new DirectoryInfo(path);
                        if (dir.Exists == false)
                        {
                            WriteMessage("路径不存在!请重新输入");
                        }
                        else
                        {
                            FileName = "";
                            GetChildDicsName(dir);
                            WriteMessage(FileName);
                            Console.WriteLine("获取该路径下文件名成功!你可以继续输入新的路径");
                        }
                    }
                    path = Console.ReadLine();
                    isContinute = path != "1";
                } while (isContinute);
            }
    
            public static DirectoryInfo[] GetChildDicsName(DirectoryInfo dir)
            {
                FileInfo[] fileArray = dir.GetFiles();
                DirectoryInfo[] childDirs = dir.GetDirectories();
    
                foreach (FileInfo file in fileArray)
                {
                    FileName += file.Name + ",";
                }
                if (childDirs.Length > 0)
                {
                    foreach (DirectoryInfo dirChild in childDirs)
                    {
                        GetChildDicsName(dirChild);
                    }
                }
                return childDirs;
            }
    
            public static void WriteMessage(string message)
            {
                Console.WriteLine(message);
                //File.Create(@"C:UsersPublicDesktoptest.txt");
                FileStream fs = File.Open(@"C:UsersPublicDesktoptest.txt", FileMode.Append);
                StreamWriter sw = new StreamWriter(fs);
                sw.WriteLine(message);  //这里是写入的内容
                sw.Close();
                fs.Close();
            }
        }
    }
    

    新建一个QuartzClass类库项目。nuget控制台输入

    2.2.1

     

    图片 1

    题目

    按照本书开头所示轨迹的格式给出原地归并排序的抽象 merge() 方法是如何将数组 A E Q S U Y E I N O S T 排序的。

    控制台信息截图:

    image.png

    解答

    图片 2

     

    图片 3

     

    2.2.2

     

    添加Quartz.net的引用。
    我们新建一个JobBase.cs文件,里面有一个Run方法。之后所有的Job都需继承这个基类,并实现Run方法。

    题目

    按照算法 2.4 所示轨迹的格式给出自顶向下的归并排序是如何将数组 E A S Y Q U E S T I O N 排序的。

    namespace LY.QuartzClass
    {
    public abstract class JobBase
    {
        public abstract void Run();
    
    }
    }
    
    解答

    图片 4

     

     

    2.2.3

    之后新增一个JobInstance.cs类。这个类主要实现IJob接口。

    题目

    用自底向上的归并排序解答练习 2.2.2

    using Quartz;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    namespace LY.QuartzClass
    {
    public class JobInstance : IJob
    {
    public void Execute(IJobExecutionContext context)
    {
    IDictionary<string, object> jobs = context.JobDetail.JobDataMap;
    if (jobs != null)
    {
    foreach (var item in jobs.Values)
    {
    try
    {
    JobBase jobObj = item as JobBase;
    jobObj.Run();
    }
    catch
    {
    }
    }
    }
    }
    }
    }
    
    解答

    图片 5

     

     

    2.2.4

    在JobInstance类的Execute方法中,我们从JobDataMap中取出JobBase实体,并执行Run方法。

    题目

    是否当且仅当两个输入的子数组都有序时原地归并的抽象方法才能得到正确的结果?
    证明你的结论,或者给出一个反例。

    下面我们新增一个JobManager.cs类,类内只有一个简单的AddJob方法

    解答

    是的,必须要两个子数组都有序时归并才能得到正确结果。
    如果说数组不有序的话,那么最后只能得到两个数组的混合。
    合并后的数组中,属于原有数组的元素的相对顺序不会被改变。
    例如子数组 1 3 1 和 2 8 5 原地归并。
    结果是 1 2 3 1 8 5,其中 1 3 1 和 2 8 5 的相对顺序不变。

     

    using Quartz;
    using Quartz.Impl;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    namespace LY.QuartzClass
    {
    public class JobManage
    {
    IScheduler schedudler;
    public JobManage()
    {
    schedudler = StdSchedulerFactory.GetDefaultScheduler();
    schedudler.Start();
    }
        public void AddJob<T>(int Second) where T : JobBase
        {
    
            JobBase jbobj = Activator.CreateInstance<T>();
            IDictionary<string, object> jbData = new Dictionary<string, object>();
            jbData.Add("name", jbobj);
    
            IJobDetail job1 = JobBuilder.Create<JobInstance>()
                .SetJobData(new JobDataMap(jbData)).Build();
    
            ITrigger trigger1 = TriggerBuilder.Create()
                .StartNow()
                .WithSimpleSchedule(x => x.WithIntervalInSeconds(Second)
                .RepeatForever()).Build();
    
            schedudler.ScheduleJob(job1, trigger1);
    
        }
    
       public void AddJob<T>(string rule) where T : JobBase
        {
            JobBase jbInstance = Activator.CreateInstance<T>();
            IDictionary<string, object> jbData = new Dictionary<string, object>();
            jbData.Add("name", jbInstance);
    
            IJobDetail job1 = JobBuilder.Create<JobInstance>()
                .SetJobData(new JobDataMap(jbData)).Build();
    
            ITrigger trigger1 = TriggerBuilder.Create()
                .StartNow()
                .WithCronSchedule(rule).Build();
    
            schedudler.ScheduleJob(job1, trigger1);
        }
    }
    }
    

    2.2.5

     

    题目

    当输入数组的大小 N=39 时,给出自顶向下和自底向上的归并排序中各次归并子数组的大小及顺序。

    在AddJob时,将Job传入JobData中。

    解答

    每次归并子数组的大小和顺序如下:

    自顶向下

    2, 3, 2, 5, 2, 3, 2, 5, 10, 2, 3, 2, 5, 2, 3, 2, 5, 10, 20, 2, 3, 2, 5, 2, 3, 2, 5, 10, 2, 3, 2, 5, 2, 2, 4, 9, 19, 39

    自底向上

    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 8, 8, 8, 8, 7, 16, 16, 32, 39

     

    下面我们进行调用Test。
    新建一个窗体项目,并添加对LY.QuartzClass项目的引用。
    新增三个Job类,继承自JobBase

    2.2.6

    public class FirstJob : JobBase
    {
    public override void Run()
    {
    Console.WriteLine(DateTime.Now.ToString());
    }
    }
    
    题目

    编写一个程序来计算自顶向下和自底向上的归并排序访问数组的准确次数。
    使用这个程序将 N=1 至 512 的结果绘成曲线图,并将其和上限 6NlgN 相比较。

     

    解答

    图片 6

    灰色是上限,蓝点是自顶向下,红点是自底向上。
    由于两种排序访问数组的次数是一样的,因此蓝点和红点重合。

    public class SecondJob : JobBase
    {
    public override void Run()
    {
    Console.WriteLine(DateTime.Now.ToString() + ":Hello");
    }
    }
    
    代码

    给出绘图部分的代码:

    using System;
    using System.Windows.Forms;
    using System.Drawing;
    using Merge;
    
    namespace _2._2._6
    {
        /*
         * 2.2.6
         * 
         * 编写一个程序来计算自顶向下和自底向上的归并排序访问数组的准确次数。
         * 使用这个程序将 N=1 至 512 的结果绘成曲线图,
         * 并将其和上限 6NlgN 相比较。
         * 
         */
        static class Program
        {
            /// <summary>
            /// 应用程序的主入口点。
            /// </summary>
            [STAThread]
            static void Main()
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Compute();
                Application.Run(new Form1());
            }
    
            static void Compute()
            {
                MergeSort mergeSort = new MergeSort();
                MergeSortBU mergeSortBU = new MergeSortBU();
                int[] mergeResult = new int[10];
                int[] mergeResultBU = new int[10];
                int[] upperBound = new int[10];
    
                // 进行计算
                int dataSize = 1;
                for (int i = 0; i < 10; i++)
                {
                    int[] dataMerge = SortCompare.GetRandomArrayInt(dataSize);
                    int[] dataMergeBU = new int[dataSize];
                    dataMerge.CopyTo(dataMergeBU, 0);
    
                    mergeSort.ClearArrayVisitCount();
                    mergeSortBU.ClearArrayVisitCount();
                    mergeSort.Sort(dataMerge);
                    mergeSortBU.Sort(dataMergeBU);
    
                    mergeResult[i] = mergeSort.GetArrayVisitCount();
                    mergeResultBU[i] = mergeSortBU.GetArrayVisitCount();
                    upperBound[i] = (int)(6 * dataSize * Math.Log(dataSize, 2));
    
                    dataSize *= 2;
                }
    
                // 绘图
                Form2 plot = new Form2();
                plot.Show();
                Graphics graphics = plot.CreateGraphics();
    
                // 获得绘图区矩形。
                RectangleF rect = plot.ClientRectangle;
                float unitX = rect.Width / 10;
                float unitY = rect.Width / 10;
    
                // 添加 10% 边距作为文字区域。
                RectangleF center = new RectangleF
                    (rect.X + unitX, rect.Y + unitY,
                    rect.Width - 2 * unitX, rect.Height - 2 * unitY);
    
                // 绘制坐标系。
                graphics.DrawLine(Pens.Black, center.Left, center.Top, center.Left, center.Bottom);
                graphics.DrawLine(Pens.Black, center.Left, center.Bottom, center.Right, center.Bottom);
                graphics.DrawString("28000", plot.Font, Brushes.Black, rect.Location);
                graphics.DrawString("1024", plot.Font, Brushes.Black, center.Right, center.Bottom);
                graphics.DrawString("0", plot.Font, Brushes.Black, rect.Left, center.Bottom);
    
                // 初始化点。
                PointF[] grayPoints = new PointF[10]; // 上限
                PointF[] redPoints = new PointF[10];  // 自顶向下
                PointF[] bluePoints = new PointF[10]; // 自底向上
                unitX = center.Width / 11.0f;
                unitY = center.Height / 28000.0f;
    
                for (int i = 0; i < 10; i++)
                {
                    grayPoints[i] = new PointF(center.Left + unitX * (i + 1), center.Bottom - (upperBound[i] * unitY) - 10);
                    redPoints[i] = new PointF(center.Left + unitX * (i + 1), center.Bottom - (mergeResult[i] * unitY) - 10);
                    bluePoints[i] = new PointF(center.Left + unitX * (i + 1), center.Bottom - (mergeResultBU[i] * unitY) - 10);
                }
    
                // 绘制点。
                for (int i = 0; i < 10; i++)
                {
                    graphics.FillEllipse(Brushes.Gray, new RectangleF(grayPoints[i], new SizeF(10, 10)));
                    graphics.FillEllipse(Brushes.Red, new RectangleF(redPoints[i], new SizeF(10, 10)));
                    graphics.FillEllipse(Brushes.Blue, new RectangleF(bluePoints[i], new Size(10, 10)));
                }
    
                graphics.Dispose();
            }
        }
    }
    

     

     

    2.2.7

    public class ThirdJob : JobBase
    {
    public override void Run()
    {
    Console.WriteLine(DateTime.Now.ToString() + ":CronTest");
    }
    }
    
    题目

    证明归并排序的比较次数是单调递增的(即对于 N>0,C(N+1)>C(N))。

     

    解答

    根据书本给出的命题 G 和命题 H(中文版 P173/176,英文版 P275/279),
    比较次数的下限 C(N) = 1/2 * NlgN
    N 和 lgN 都是单调递增且大于零的(N>1),因此 C(N) 也是单调递增的

     

    在窗体中进行调用

    2.2.8

    private void button1_Click(object sender, EventArgs e)
    {
    JobManage job = new JobManage();
    job.AddJob<FirstJob>(3);
    job.AddJob<SecondJob>(6);
    job.AddJob<ThirdJob>("0/5 0-58 9 * * ?");
    }
    
    题目

    假设将算法 2.4 修改为:
    只要 a[mid] <= a[mid+1] 就不调用 merge() 方法,
    请证明用归并排序处理一个已经有序的数组所需的比较次数是线性级别的。

     

    解答

    修改后的算法对已经有序的情况做了优化
    数组对半切分并排序后,
    如果 a[mid] < a[mid + 1](左半部分的最后一个元素小于右半部分的第一个元素)
    那么我们可以直接合并数组,不需要再做多余的操作

    现在的输入是一个已经排序的数组
    算法唯一的比较发生在判断 a[mid] < a[mid + 1] 这个条件时
    假定数组有 N 个元素
    比较次数满足 T(N) = 2 * T(N / 2) + 1, T(1) = 0
    转化为非递归形式即为:T(N) = cN / 2 + N - 1
    其中 c 为任意正整数

     

    结果如下:

    2.2.9

     

    题目

    在库函数中使用 aux[] 这样的静态数组时不妥当的,
    因为可能会有多个程序同时使用这个类。
    实现一个不用静态数组的 Merge 类,
    但也不要将 aux[] 变为 merge() 的局部变量(请见本书的答疑部分)。
    提示:可以将辅助数组作为参数传递给递归的 sort() 方法。

     

    解答

    官方给出的归并排序实现中在 Sort 方法里初始化了 aux 数组。
    源码见:

    C#实现和官方的实现非常类似,

    首先定义只接受一个参数的公开 Sort 方法,在这个方法里面初始化 aux 数组。

    /// <summary>
    /// 利用归并排序将数组按升序排序。
    /// </summary>
    /// <typeparam name="T">数组元素类型。</typeparam>
    /// <param name="a">待排序的数组。</param>
    public override void Sort<T>(T[] a)
    {
        T[] aux = new T[a.Length];
        Sort(a, aux, 0, a.Length - 1);
    }
    

    然后建立一个私有的递归 Sort 方法做实际的排序操作。

    /// <summary>
    /// 自顶向下地对数组指定范围内进行归并排序,需要辅助数组。
    /// </summary>
    /// <typeparam name="T">需要排序的元素类型。</typeparam>
    /// <param name="a">原数组。</param>
    /// <param name="aux">辅助数组。</param>
    /// <param name="lo">排序范围起点。</param>
    /// <param name="hi">排序范围终点。</param>
    private void Sort<T>(T[] a, T[] aux, int lo, int hi) where T : IComparable<T>
    {
        if (hi <= lo)
            return;
        int mid = lo + (hi - lo) / 2;
        Sort(a, aux, lo, mid);
        Sort(a, aux, mid + 1, hi);
        Merge(a, aux, lo, mid, hi);
    }
    

    图片 7

    代码
    using System;
    
    namespace Merge
    {
        /// <summary>
        /// 归并排序类。
        /// </summary>
        public class MergeSort : BaseSort
        {
            /// <summary>
            /// 默认构造函数。
            /// </summary>
            public MergeSort() { }
    
            /// <summary>
            /// 利用归并排序将数组按升序排序。
            /// </summary>
            /// <typeparam name="T">数组元素类型。</typeparam>
            /// <param name="a">待排序的数组。</param>
            public override void Sort<T>(T[] a)
            {
                T[] aux = new T[a.Length];
                Sort(a, aux, 0, a.Length - 1);
            }
    
            /// <summary>
            /// 自顶向下地对数组指定范围内进行归并排序,需要辅助数组。
            /// </summary>
            /// <typeparam name="T">需要排序的元素类型。</typeparam>
            /// <param name="a">原数组。</param>
            /// <param name="aux">辅助数组。</param>
            /// <param name="lo">排序范围起点。</param>
            /// <param name="hi">排序范围终点。</param>
            private void Sort<T>(T[] a, T[] aux, int lo, int hi) where T : IComparable<T>
            {
                if (hi <= lo)
                    return;
                int mid = lo + (hi - lo) / 2;
                Sort(a, aux, lo, mid);
                Sort(a, aux, mid + 1, hi);
                Merge(a, aux, lo, mid, hi);
            }
    
            /// <summary>
            /// 将指定范围内的元素归并。
            /// </summary>
            /// <typeparam name="T">数组元素类型。</typeparam>
            /// <param name="a">原数组。</param>
            /// <param name="aux">辅助数组。</param>
            /// <param name="lo">范围起点。</param>
            /// <param name="mid">范围中点。</param>
            /// <param name="hi">范围终点。</param>
            private void Merge<T>(T[] a, T[] aux, int lo, int mid, int hi) where T : IComparable<T>
            {
                for (int k = lo; k <= hi; k++)
                {
                    aux[k] = a[k];
                }
    
                int i = lo, j = mid + 1;
                for (int k = lo; k <= hi; k++)
                {
                    if (i > mid)
                    {
                        a[k] = aux[j];
                        j++;
                    }
                    else if (j > hi)
                    {
                        a[k] = aux[i];
                        i++;
                    }
                    else if (Less(aux[j], aux[i]))
                    {
                        a[k] = aux[j];
                        j++;
                    }
                    else
                    {
                        a[k] = aux[i];
                        i++;
                    }
                }
            }
        }
    }
    

     

    image.png

    2.2.10

    题目

    快速归并。
    实现一个 merge() 方法,按降序将 a[] 的后半部分复制到 aux[],
    然后将其归并回 a[] 中。这样就可以去掉内循环中检测某半边是否用尽的代码。
    注意:这样的排序产生的结果是不稳定的(请见 2.5.1.8 节)。

    解答

    官方同样给出了 java 实现,如下:

    private static void merge(Comparable[] a, int lo, int mid, int hi) { 
       for (int i = lo; i <= mid; i++)
          aux[i] = a[i]; 
    
       for (int j = mid+1; j <= hi; j++)
          aux[j] = a[hi-j+mid+1];
    
       int i = lo, j = hi; 
       for (int k = lo; k <= hi; k++) 
          if (less(aux[j], aux[i])) a[k] = aux[j--];
          else                      a[k] = aux[i++];
    }
    

    C# 实现见代码部分。

    代码
    using System;
    using Merge;
    
    namespace _2._2._10
    {
        /// <summary>
        /// 归并排序类。
        /// </summary>
        public class MergeSort : BaseSort
        {
            /// <summary>
            /// 默认构造函数。
            /// </summary>
            public MergeSort() { }
    
            /// <summary>
            /// 利用归并排序将数组按升序排序。
            /// </summary>
            /// <typeparam name="T">数组元素类型。</typeparam>
            /// <param name="a">待排序的数组。</param>
            public override void Sort<T>(T[] a)
            {
                T[] aux = new T[a.Length];
                Sort(a, aux, 0, a.Length - 1);
            }
    
            /// <summary>
            /// 自顶向下地对数组指定范围内进行归并排序,需要辅助数组。
            /// </summary>
            /// <typeparam name="T">需要排序的元素类型。</typeparam>
            /// <param name="a">原数组。</param>
            /// <param name="aux">辅助数组。</param>
            /// <param name="lo">排序范围起点。</param>
            /// <param name="hi">排序范围终点。</param>
            private void Sort<T>(T[] a, T[] aux, int lo, int hi) where T : IComparable<T>
            {
                if (hi <= lo)
                    return;
                int mid = lo + (hi - lo) / 2;
                Sort(a, aux, lo, mid);
                Sort(a, aux, mid + 1, hi);
                Merge(a, aux, lo, mid, hi);
            }
    
            /// <summary>
            /// 将指定范围内的元素归并。
            /// </summary>
            /// <typeparam name="T">数组元素类型。</typeparam>
            /// <param name="a">原数组。</param>
            /// <param name="aux">辅助数组。</param>
            /// <param name="lo">范围起点。</param>
            /// <param name="mid">范围中点。</param>
            /// <param name="hi">范围终点。</param>
            private void Merge<T>(T[] a, T[] aux, int lo, int mid, int hi) where T : IComparable<T>
            {
                // 前半部分升序复制
                for (int k = lo; k <= mid; k++)
                {
                    aux[k] = a[k];
                }
                // 后半部分降序复制
                for (int k = mid + 1; k <= hi; k++)
                {
                    aux[k] = a[hi - k + mid + 1];
                }
    
                // i 指向最左端,j 指向最右端
                int i = lo, j = hi;
                for (int k = lo; k <= hi; k++)
                {
                    if (Less(aux[j], aux[i]))
                    {
                        a[k] = aux[j];
                        j--;
                    }
                    else
                    {
                        a[k] = aux[i];
                        i++;
                    }
                }
            }
        }
    }
    

     

    2.2.11

    题目

    改进。
    实现 2.2.2 节所述的对归并排序的三项改进:
    加快小数组的排序速度,
    检测数组是否已经有序以及通过在递归中交换参数来避免复制。

    本文由金沙国际官网发布于编程,转载请注明出处:net的简单封装,包括子文件夹

    关键词: