【C#数据结构与算法 Marcin Jamro】第三章 堆栈和队列

堆栈:反转字符串、河内塔问题

队列: 呼叫中心单顾问、呼叫中心多顾问

优先级队列Priority queues:  呼叫中心优先级支持



//    第三章 stacks  and queues ///
//  1.1  ReverseWords  反转字符串
					!ESREVER S'TEL
        static void Main(string[] args)
        {
            Stack<char> chars = new Stack<char>();
            foreach (char c in "LET'S REVERSE!")
            {
                chars.Push(c);
            }

            while (chars.Count > 0)
            {
                Console.Write(chars.Pop());
            }
            Console.WriteLine();
            Console.ReadLine(); 
        }


///  1.2  Tower of  Hanoi   河内塔 
         FROM                  TO                AUXILIARY




     ==========
    ============
   ==============
  ================
 ==================           ==                  ====
====================       ========              ======

Number of moves: 9
Number of discs: 10

/* HanoiTower.cs 河内塔类 */
using System;
using System.Collections.Generic;

namespace HanoiTowers
{
    public class HanoiTower //河内塔
    {
        public int DiscsCount { get; private set; } //总盘数
        public int MovesCount { get; private set; }  //总移动次数
        public Stack<int> From { get; private set; }
        public Stack<int> To { get; private set; }
        public Stack<int> Auxiliary { get; private set; }
        public event EventHandler<EventArgs> MoveCompleted; //移动完成事件处理器
        //构造函数
        public HanoiTower(int discs)
        {
            DiscsCount = discs;//总盘数
            From = new Stack<int>();
            To = new Stack<int>();
            Auxiliary = new Stack<int>();
            for (int i = 1; i <= discs; i++)
            {
                int size = discs - i + 1;
                From.Push(size);//初始化From 堆栈
            }
        }
        //开始移动
        public void Start()
        {
            Move(DiscsCount, From, To, Auxiliary);
        }
        //移动   递归移动
        public void Move(int discs, Stack<int> from, Stack<int> to, Stack<int> auxiliary)
        {
            if (discs > 0)
            {
                Move(discs - 1, from, auxiliary, to);//将discs-1 个盘子 先放在辅助棒子auxiliary上

                to.Push(from.Pop());//把from最底下的取出 放在to上
                MovesCount++;//总移动次数
                MoveCompleted?.Invoke(this, EventArgs.Empty); //完成搬运一次触发可视化

                Move(discs - 1, auxiliary, to, from);//将辅助棒子auxiliary上的discs-1个盘子放到 to上
            }
        }
    }
}
/* Main 程序  */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;

namespace HanoiTowers
{
    class Program
    {
        private const int DISCS_COUNT = 10;//盘数
        private const int DELAY_MS = 250;//延迟时间
        private static int _columnSize = 30;

        static void Main(string[] args)
        {
            _columnSize = Math.Max(6, GetDiscWidth(DISCS_COUNT) + 2);// 每个堆栈的列数
            HanoiTower algorithm = new HanoiTower(DISCS_COUNT);//构造河内塔
            algorithm.MoveCompleted += Algorithm_Visualize;//完成一次搬运事件绑定处理方法
            Algorithm_Visualize(algorithm, EventArgs.Empty);//调用一次算法可视化
            algorithm.Start(); //开始移动
            Console.ReadLine();
        }
        //没完成一次搬运触发可视化更新
        private static void Algorithm_Visualize(object sender, EventArgs e)
        {
            Console.Clear();

            HanoiTower algorithm = (HanoiTower)sender;//获取河内塔对象
            if (algorithm.DiscsCount <= 0) { return; }

            char[][] visualization = InitializeVisualization(algorithm);//初始化河内塔可视化数据
            PrepareColumn(visualization, 1, algorithm.DiscsCount, algorithm.From);
            PrepareColumn(visualization, 2, algorithm.DiscsCount, algorithm.To);
            PrepareColumn(visualization, 3, algorithm.DiscsCount, algorithm.Auxiliary);

            Console.WriteLine(Center("FROM") + Center("TO") + Center("AUXILIARY"));  //先输出每个堆栈的居中标题   
            DrawVisualization(visualization);
            Console.WriteLine();
            Console.WriteLine($"Number of moves: {algorithm.MovesCount}");//总移动次数
            Console.WriteLine($"Number of discs: {algorithm.DiscsCount}");

            Thread.Sleep(DELAY_MS);
        }
        //初始化河内塔可视化数据 二维字符数组 为空格
        private static char[][] InitializeVisualization(HanoiTower algorithm)
        {
            char[][] visualization = new char[algorithm.DiscsCount][]; //DiscsCount 层

            for (int y = 0; y < visualization.Length; y++)//遍历每一层
            {
                visualization[y] = new char[_columnSize * 3]; //初始化每一层
                for (int x = 0; x < _columnSize * 3; x++)
                {
                    visualization[y][x] = ' ';//每个数据位空格
                }
            }

            return visualization;
        }
        //准备列
        private static void PrepareColumn(char[][] visualization, int column, int discsCount, Stack<int> stack)
        {
            int margin = _columnSize * (column - 1);//第几列左边界

            for (int y = 0; y < stack.Count; y++)//准备堆栈的每行数据
            {
                int size = stack.ElementAt(y);//第y个盘的尺寸
                int row = discsCount - (stack.Count - y);//确定盘所在行
                int columnStart = margin + discsCount - size;//盘左边界
                int columnEnd = columnStart + GetDiscWidth(size);// 盘右边界

                for (int x = columnStart; x <= columnEnd; x++) //
                {
                    visualization[row][x] = '=';
                }
            }
        }
        //输出堆栈数据
        private static void DrawVisualization(char[][] visualization)
        {
            for (int y = 0; y < visualization.Length; y++)
            {
                Console.WriteLine(visualization[y]);//输出每层字符串数组
            }
        }
        //每列居中输出字符串  FROM TO AUXILIARY
        private static string Center(string text)
        {
            int margin = (_columnSize - text.Length) / 2;
            return text.PadLeft(margin + text.Length).PadRight(_columnSize);
        }
        //获取盘宽度
        private static int GetDiscWidth(int size)
        {
            return 2 * size - 1;
        }
    }
}



//  2.1  无优先级的呼叫中心   队列
				[09:30:52] Call #1 from 1234 is answered by Marcin.
				[09:30:59] Call #1 from 1234 is ended by Marcin.
				[09:30:59] Call #2 from 5678 is answered by Marcin.
				[09:31:08] Call #2 from 5678 is ended by Marcin.
				[09:31:08] Call #3 from 1468 is answered by Marcin.
				[09:31:11] Call #3 from 1468 is ended by Marcin.
				[09:31:11] Call #4 from 9641 is answered by Marcin.
				[09:31:19] Call #4 from 9641 is ended by Marcin.

/*Main 程序*/
    class Program
    {
        static void Main(string[] args)
        {
            Random random = new Random();

            CallCenter center = new CallCenter();
            center.Call(1234);
            center.Call(5678);
            center.Call(1468);
            center.Call(9641);

            while (center.AreWaitingCalls())
            {
                IncomingCall call = center.Answer("Marcin");//取出呼叫进行应答
                Log($"Call #{call.Id} from {call.ClientId} is answered by {call.Consultant}.");
                Thread.Sleep(random.Next(1000, 10000));
                center.End(call);//结束呼叫
                Log($"Call #{call.Id} from {call.ClientId} is ended by {call.Consultant}.");
            }
            Console.ReadLine(); 
        }

        private static void Log(string text)
        {
            Console.WriteLine($"[{DateTime.Now.ToString("HH:mm:ss")}] {text}");
        }
    }
/*  CallCenter 呼叫中心类 */
    public class CallCenter
    {
        private int _counter = 0;
        public Queue<IncomingCall> Calls { get; private set; }

        public CallCenter()
        {
            Calls = new Queue<IncomingCall>();
        }

        public void Call(int clientId)
        {
            IncomingCall call = new IncomingCall()
            {
                Id = ++_counter,
                ClientId = clientId,
                CallTime = DateTime.Now
            };
            Calls.Enqueue(call);
        }

        public IncomingCall Answer(string consultant)
        {
            if (Calls.Count > 0)
            {
                IncomingCall call = Calls.Dequeue();
                call.Consultant = consultant;
                call.StartTime = DateTime.Now;
                return call;
            }
            return null;
        }

        public void End(IncomingCall call)
        {
            call.EndTime = DateTime.Now;
        }

        public bool AreWaitingCalls()
        {
            return Calls.Count > 0;
        }
    }
/* 来电类*/
    public class IncomingCall //来电
    {
        public int Id { get; set; }
        public int ClientId { get; set; }
        public DateTime CallTime { get; set; }
        public DateTime StartTime { get; set; }
        public DateTime EndTime { get; set; }
        public string Consultant { get; set; }
        public bool IsPriority { get; set; }
    }



/   3.1   呼叫中心 优先级:  callcenterpriority
			[08:52:27] Call #2 from 5678 is answered by Marcin / Mode: priority.
			[08:52:35] Call #2 from 5678 is ended by Marcin.
			[08:52:35] Call #4 from 9641 is answered by Marcin / Mode: priority.
			[08:52:38] Call #4 from 9641 is ended by Marcin.
			[08:52:38] Call #1 from 1234 is answered by Marcin / Mode: normal.
			[08:52:48] Call #1 from 1234 is ended by Marcin.
			[08:52:48] Call #3 from 1468 is answered by Marcin / Mode: normal.
			[08:52:56] Call #3 from 1468 is ended by Marcin.


/* 呼叫中心类       添加nuget包 OptimizedPriorityQueue */
using Priority_Queue;
using System;

namespace CallCenterPriority
{
    public class CallCenter //呼叫中心
    {
        private int _counter = 0;
        public SimplePriorityQueue<IncomingCall> Calls { get; private set; } //来电(优先级队列)

        public CallCenter() //构造函数:实例化来电队列
        {
            Calls = new SimplePriorityQueue<IncomingCall>();
        }
        //增加来电
        public void Call(int clientId, bool isPriority = false)
        {
            IncomingCall call = new IncomingCall()
            {
                Id = ++_counter,
                ClientId = clientId,
                CallTime = DateTime.Now,
                IsPriority = isPriority
            };
            Calls.Enqueue(call, isPriority ? 0 : 1);
        }
        //开始处理来电
        public IncomingCall Answer(string consultant)
        {
            if (Calls.Count > 0)
            {
                IncomingCall call = Calls.Dequeue();
                call.Consultant = consultant;
                call.StartTime = DateTime.Now;
                return call;
            }
            return null;
        }
        //结束处理来电
        public void End(IncomingCall call)
        {
            call.EndTime = DateTime.Now;
        }
        //等待的来电数
        public bool AreWaitingCalls()
        {
            return Calls.Count > 0;
        }
    }
}

/*Main 程序 */
        static void Main(string[] args)
        {
            Random random = new Random();

            CallCenter center = new CallCenter();
            center.Call(1234);
            center.Call(5678, true);
            center.Call(1468);//
            center.Call(9641, true);

            while (center.AreWaitingCalls())
            {
                IncomingCall call = center.Answer("Marcin");//处理来电
                Log($"Call #{call.Id} from {call.ClientId} is answered by {call.Consultant} / Mode: {(call.IsPriority ? "priority" : "normal")}.");
                Thread.Sleep(random.Next(1000, 10000));
                center.End(call);//结束处理来电
                Log($"Call #{call.Id} from {call.ClientId} is ended by {call.Consultant}.");
            }
            Console.ReadLine();
        }

        private static void Log(string text)
        {
            Console.WriteLine($"[{DateTime.Now.ToString("HH:mm:ss")}] {text}");
        }
    }

// 3.2  并行执行  CallCenterMany   三个顾问线程池线程 应答  1个随机增加呼叫的线程
				[09:22:34] Incoming call from 5491, waiting in the queue: 1
				[09:22:34] Call #1 from 5491 is answered by Marcin.
				[09:22:37] Call #1 from 5491 is ended by Marcin.
				[09:22:37] Incoming call from 8784, waiting in the queue: 1
				[09:22:37] Call #2 from 8784 is answered by James.
				[09:22:40] Call #2 from 8784 is ended by James.
				[09:22:41] Incoming call from 7664, waiting in the queue: 1
				[09:22:41] Call #3 from 7664 is answered by Olivia.
				[09:22:44] Call #3 from 7664 is ended by Olivia.
				[09:22:45] Incoming call from 5008, waiting in the queue: 1
				[09:22:45] Call #4 from 5008 is answered by Olivia.
				[09:22:47] Incoming call from 5727, waiting in the queue: 1
				[09:22:47] Call #5 from 5727 is answered by Marcin.
				[09:22:49] Incoming call from 6093, waiting in the queue: 1
				[09:22:49] Call #6 from 6093 is answered by James.
				[09:22:52] Call #4 from 5008 is ended by Olivia.
				[09:22:54] Incoming call from 7678, waiting in the queue: 1
				[09:22:54] Call #7 from 7678 is answered by Olivia.
				[09:22:55] Call #5 from 5727 is ended by Marcin.
				[09:22:56] Incoming call from 3204, waiting in the queue: 1
				[09:22:56] Call #8 from 3204 is answered by Marcin.
				[09:22:57] Call #6 from 6093 is ended by James.
				[09:22:57] Incoming call from 2799, waiting in the queue: 1
				[09:22:57] Call #9 from 2799 is answered by James.
				[09:22:58] Incoming call from 5693, waiting in the queue: 1
				[09:22:59] Incoming call from 8044, waiting in the queue: 2
				[09:23:00] Call #7 from 7678 is ended by Olivia.
				[09:23:01] Call #10 from 5693 is answered by Olivia.
				[09:23:02] Call #8 from 3204 is ended by Marcin.
				[09:23:02] Call #11 from 8044 is answered by Marcin.
				……

/* Main  程序 */
using System;
using System.Threading;
using System.Threading.Tasks;

namespace CallCenterMany
{
    class Program
    {
        static void Main(string[] args)
        {
            CallCenter center = new CallCenter();
            Parallel.Invoke(//尽可能并行执行提供的每个操作
                () => CallersAction(center), //1个呼叫线程
                () => ConsultantAction(center, "Marcin", ConsoleColor.Red),//3个顾问应答线程
                () => ConsultantAction(center, "James", ConsoleColor.Yellow),
                () => ConsultantAction(center, "Olivia", ConsoleColor.Green));
            Console.ReadLine();
        }
        //呼叫着动作
        private static void CallersAction(CallCenter center)
        {
            Random random = new Random();
            while (true)
            {
                int clientId = random.Next(1, 10000);
                int waitingCount = center.Call(clientId);//增加随机客户端clientId的呼叫,并返回总呼叫数
                Log($"Incoming call from {clientId}, waiting in the queue: {waitingCount}");
                Thread.Sleep(random.Next(1000, 5000));
            }
        }
        //顾问动作
        private static void ConsultantAction(CallCenter center, string name, ConsoleColor color)
        {
            Random random = new Random();
            while (true)
            {
                IncomingCall call = center.Answer(name);//尝试取出一个呼叫,开始应答
                if (call != null)
                {
                    Console.ForegroundColor = color;
                    Log($"Call #{call.Id} from {call.ClientId} is answered by {call.Consultant}.");
                    Console.ForegroundColor = ConsoleColor.Gray;

                    Thread.Sleep(random.Next(1000, 10000));
                    center.End(call);//结束应答

                    Console.ForegroundColor = color;
                    Log($"Call #{call.Id} from {call.ClientId} is ended by {call.Consultant}.");
                    Console.ForegroundColor = ConsoleColor.Gray;

                    Thread.Sleep(random.Next(500, 1000));
                }
                else
                {
                    Thread.Sleep(100);
                }
            }
        }

        private static void Log(string text)
        {
            Console.WriteLine($"[{DateTime.Now.ToString("HH:mm:ss")}] {text}");
        }
    }
}

/*呼叫中心  略有改变*/
    public class CallCenter
    {
        private int _counter = 0;
        public ConcurrentQueue<IncomingCall> Calls { get; private set; }

        public CallCenter()
        {
            Calls = new ConcurrentQueue<IncomingCall>();
        }

        public int Call(int clientId)
        {
            IncomingCall call = new IncomingCall()
            {
                Id = ++_counter,
                ClientId = clientId,
                CallTime = DateTime.Now
            };
            Calls.Enqueue(call);
            return Calls.Count;
        }

        public IncomingCall Answer(string consultant)
        {
            if (Calls.Count > 0 && Calls.TryDequeue(out IncomingCall call))//尝试取出一个呼叫进行应答
            {
                call.Consultant = consultant;
                call.StartTime = DateTime.Now;
                return call;
            }
            return null;
        }

        public void End(IncomingCall call)
        {
            call.EndTime = DateTime.Now;
        }

        public bool AreWaitingCalls()
        {
            return Calls.Count > 0;
        }
    }
	

猜你喜欢

转载自blog.csdn.net/cxyhjl/article/details/129687060