使用递归查询地区
开发工具与关键技术:Visual Studio 2015、SQL Server 2014 Management Studio、C#、JavaScript
作者: 饶芝华
撰写时间:2019年01月 18日
这是数据库的一张部分地区表:
此表设计借鉴麦志坚师兄,这张表有三个字段,第一个是主键ID,第二个是地区父ID,第三个是详细地区名字。地区父ID这个字段主要是用来标识每个地区的父级,比如广东的ID是4,那么广州、深圳、佛山它们的地区父ID就是4都是属于广东管辖地区。其实也是一种树形结构。
我们都知道,递归思维非常有特点,一个含参函数自己调用自己甚至无限次的被调用最后一次次的返回结果。可是它的代码写法不同,返回的顺序就往往令人琢磨不透,为啥嘞?因为,堆栈!
不妨先看第几种写法:
Names:用来存放输出的地区名称列表;
DiQvFarID:地区父ID;
DiQvID:地区ID;
DiQvMC:地区名称;
public ActionResult myDiGui()
{
return View();
}
public static List<string> Names = new List<string>();
public ActionResult Helphandle()
{
selectDQ(0);
return Json(Names, JsonRequestBehavior.AllowGet);
}
public void selectDQ(int ID)
{
List<DIGui> diqv = (from tbDiQv in myModels.bsn_DiQv
where tbDiQv.DiQvfarID == ID
select new DIGui
{
DiQvMC = tbDiQv.DiQvMC,
DiQvID = tbDiQv.DiQvID
}).ToList();
if (diqv.Count > 0)
{
for (int i = 0; i < diqv.Count; i++)
{
//Names.Add(diqv[i].DiQvMC);//正序
selectDQ(diqv[i].DiQvID);//递归参数
Names.Add(diqv[i].DiQvMC);//倒序,压入在堆栈中,这句代码相当于从上往下被一层一层的叠了起来。最后一次放在最顶层。
}
}
}
在selectDQ(int ID)这个函数中,第一行就是根据参数ID筛选地区表中与地区父ID相同的所有地区名称和地区ID列表。这里调用selectDQ(int 0),从中国开始查询。
第二行判断diqv中是否有数据,有的话则循环这个列表往静态成员Names中添加本次查询出的地区名称,然后就是递归当前被添加的地区ID,直到满足终止条件。
<div style="margin-left:100px;">
<p style="font-size:30px;">点击按钮1查询出所有的地区</p>
<button id="btn1">按钮1</button>
<div id="one"></div>
</div>
<script src="~/Content/jquery-1.12.4/jquery-1.12.4.js"></script>
<script src="~/Content/js/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
<script>
$("#btn1").click(function () {
$.getJSON("Helphandle", function (data) {
for (var i = 0; i < data.length; i++) {
$("#one").append("<p style='font-size:30px;'>"+data[i] + "</p></br>");
}
});
});
</script>
循环返回的数据输出结果如图:
代码说明:这就好比中国下面有:北京、上海、广东、浙江,当北京被加入Names列表之后,紧接着递归北京ID,通过查询并判断发现地区表里面地区父ID(DiQuFarID)为2的地区不存在,也就是在这张表里面北京没有子节点,此时递归北京ID就结束了,继续循环,同理上海也没有子节点,当for循环到广东省的时候它下面有许多子节点,甚至子节点里面还有子节点。当递归到广东ID时,它的子节点广州、惠州等地区会被“刨根问底”的查询显示,直到广东省“最小的一个地区”被递归时广东ID才算递归结束,最后浙江也被加入Names列表。
如果把 Names.Add(diqv[i].DiQvMC) 放在 selectDQ(diqv[i].DiQvID)之后,页面输出
的结果如图:
很显然,“中国”在最后被输出,是不是每一次子节点地递归结果都倒序了?
前面提到,堆栈。它是一个“临时存放代码”的地方。按理说正常的倒序倒数第二个也应该是“北京”啊?不是的,当中国ID被递归时,“中国”就被压在了最底层等待加入Names。
那它是什么样的寄存顺序的呢?
存放的时候就像串冰糖葫芦一样,第一个放在最底下,往往也是最大的,最后一个放在最上面。
相反,吃的时候就从上往下一个个吃掉是吧!
同理,这里的代码不同之处无非就是“串”冰糖葫芦的过程中出现“一小串”也要“串”进去,“吃”的时候也不要激动,吃到小串的时候顺序不变,还是从上往下一个一个的“吃”。
压入堆栈的时候顺序就像:1、2、3、4、5、6、7、8、9>(a、b、c)、10
执行返回的顺序:10、(c、b、a)<9、8、7、6、5、4、3、2、1
这里的a b c就类比“一小串”。
这就是我理解的递归返回顺序,若有不足之处还请多指教!