summaryrefslogtreecommitdiff
path: root/Assets/Algorithms/Recursion/Recursion.cs
blob: 7bfb1716a756abe53c8a29be2adc4dd72a4950ff (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
using System;
using System.Collections;
using System.Collections.Generic;
using AlgorithmCollection;
using UnityEngine;

// 递归与分治算法
namespace AlgorithmCollection.Recursion
{

    public static class RecursionHelper
    {
        #region 全排列,返回数据的所有组合
        public static void Permutations<T>(List<T> dataList, ref List<List<T>> perms) 
        {                                                                             
            List<List<T>> outPerms = new List<List<T>>();                            //  A B C D 
			List<T> temp = new List<T>(dataList.Count);                              //  + A (BCD)
			DNC(                                                                     //  	+ B (CD)
				() => // init                                            	         //  		+ C(D)
				{                                                                    //  			+D
					DivisionDescriptor div = new DivisionDescriptor();               //  		+ D(C)
					div.userdata = -1;                                               //  			+C
					div.left = 0;                                                    //  	+ C (BD)
					div.right = dataList.Count - 1;                                  //  		+ B(D)
					return div;                                                      //  		+ D(B)
				},                                                                   //  	+ D (BC)
				(DivisionDescriptor div, out DivisionDescriptor[] divs) => // 划分   //  		+ B(C)
				{                                                                    //  		+ C(B)
					int left = div.left; // 包含第一个元素在内的范围			         //  + B (ACD)
					int right = div.right;                                           //  + C (ABD)
					int pivot = (int)div.userdata; // 第一个元素在范围内的索引         //  + D (ABC)
					int l = left;
					if (pivot != -1)
					{
						temp.Add(dataList[pivot]);
						Algorithms.Swap(ref dataList, pivot, left);
						l = left + 1;                                        
					}
                    divs = new DivisionDescriptor[right - l + 1];       
					int j = 0;                                               
					for (int i = l; i <= right; ++i)                         
					{
                        divs[j].left = l;
                        divs[j].right = right;
                        divs[j].userdata = (int)i;
						j++;
					}
                    return l == right;
                },
				(DivisionDescriptor div) => // solve 最小子任务处理   
				{
					temp.Add(dataList[div.left]);
					List<T> newCompose = new List<T>(temp);
					outPerms.Add(newCompose);
					temp.RemoveAt(temp.Count - 1);
				},
				(DivisionDescriptor div) => //子任务后处理
				{
					int pivot = (int)div.userdata; // 第一个元素的索引
					int left = div.left;
					int right = div.right;
					Algorithms.Swap(ref dataList, pivot, left);
					temp.RemoveAt(temp.Count - 1);
				}
            );
            perms = outPerms;
        }

        // 生成器形式,每次返回一个组合
        public static IEnumerable Permutations<T>(List<T> data)
        {
            foreach (var perm in _Permutations(data, 0, data.Count - 1))
            {
                yield return perm;
            }
        }

        // 计算start~end范围内的全排列
        private static IEnumerable _Permutations<T>(List<T> data, int start, int end, List<T> perm = null)
        {
			if (perm == null)
                perm = new List<T>(data.Count);
            if (start == end)
            {
                perm.Add(data[start]);
                yield return perm;
                perm.RemoveAt(perm.Count - 1);
            }
            else
            {
                for (int i = start; i <= end; ++i)
                {
                    perm.Add(data[i]);
                    Algorithms.Swap(ref data, start, i);
                    IEnumerator itor = _Permutations(data, start + 1, end, perm).GetEnumerator();
                    while (itor.MoveNext())
                        yield return itor.Current;
                    Algorithms.Swap(ref data, start, i);
                    perm.RemoveAt(perm.Count - 1);
                }
            }
        }
        #endregion

        #region 分治

        public delegate DivisionDescriptor Init();
        public delegate void Solve(DivisionDescriptor division);
        public delegate bool Divide(DivisionDescriptor division, out DivisionDescriptor[] divs);//返回值代表是否达到最小问题阈值
        public delegate void Merge(DivisionDescriptor[] divisions);
        public delegate void Postprocess(DivisionDescriptor div);

        // 分治算法框架
        public static void DNC(Init init, Divide divide, Solve solve, Postprocess postprocess = null, Merge merge = null)
        {
            DivisionDescriptor div = init();
            _DivideAndConquer(div, solve, divide, merge, postprocess);
        }

        private static void _DivideAndConquer(DivisionDescriptor div, Solve solve, Divide divide, Merge merge, Postprocess postprocess)
        {
            DivisionDescriptor[] division;
            bool bUnit = divide(div, out division);
            if (!bUnit)
            {
                for(int i = 0; i < division.Length; ++i)
                {
                    _DivideAndConquer(division[i], solve, divide, merge, postprocess);
                    postprocess?.Invoke(division[i]);
                }
                merge?.Invoke(division);
            }
            else
            {
                for(int i = 0; i < division.Length; ++i)
                {
                    solve(division[i]);
                }
            }
        }
        #endregion

        #region 动态规划

        private static void DP()
        {

        }
        #endregion 


    }
}