广义表(1)
2011-01-22 15:12 Clingingboy 阅读(1155) 评论(0) 编辑 收藏 举报
参考:http://blog.csdn.net/fan158/archive/2010/05/21/5613821.aspx
感谢这位作者
概念
即表中的元素可以为单个元素,同时也可以是一个表.可以说是表中有表。如下数据
A=(a,b,c,d)
B=(a,(b,c),d)
C=(a,(b,(c,d),e))
单个元素称为原子,表为子表,如B的a为原子,(b,c)为子表
将字符串转义为数组
string str = "a,b,c,d";
如上数组,若要转成数组,那么就预先要知道其大小.或者以链表方式表示
如下示例
(1)预先算数组长度
string str = "a,b,c,d"; var strLength = str.Length / 2 + 1; char[] strArr = new char[strLength]; int j = 0; for (int i = 0; i < strLength; i++) { strArr[i] = str[j]; j += 2; }
(2)用链表
string str = "a,b,c,d"; int i=0; Link<char> first = null; Link<char> currentLink = null; while (i < str.Length) { char alphabet = str[i]; var link = new Link<char>() { Value = alphabet }; if (i == 0) { first = link; currentLink = link; } else { currentLink.Next = link; currentLink = currentLink.Next; } i+=2; }
(3)递归法
public class LinkCreater { private int i = 0; Link<char> first = null; private string _str; public LinkCreater(string str) { _str = str; } public void CreatLink() { CreatLink(null); } public void CreatLink(Link<char> node) { if (i > _str.Length) return; var alphabet = _str[i]; i += 2; var link=new Link<char>() { Value = alphabet }; if (node == null) { first = link; } else { node.Next = link; } CreatLink(link); } }
public Link<char> CreatLink() { if (i > _str.Length) return first; var alphabet = _str[i]; i += 2; var link = new Link<char>() { Value = alphabet }; link.Next = CreatLink(); first = link; return first; }
构建广义表
数据结构如下
public enum NodeType { Atom, List } public class GLNode<T> { public NodeType Type { get; set; } public GLNode<T> Next { get; set; } public object Item { get; set; } //Save list or T in it by Type. }
如下数据,将其看成3个元素,当遇到子表则以相同方法递归创建子表
A=a,(b,c),f
子表创建规则:
- 若遇左括号(则创建子表
- 若遇到右括号则子表结束
- 其他状况则认为是一个原子
即除了元素之外有三种符号(),,
A=a,(b,c),f
第一步
node = new GLNode<char>(); switch (t) { case '(': node.Type = NodeType.List; node.Item = Create(); break; case ')': node = null; break; default: node.Type = NodeType.Atom; node.Item = t; break; }
1.a为Atom
2.字符前进一步,判断符号
t = this._CharArray[i++];// For Next. if (node != null) { switch (t) { case ',': node.Next = Create(); break; default: node.Next = null; break; } }
3.再次进入Create方法
4.创建子表
5….不断递归
public GLNode<char> Create() { GLNode<char> node = null; char t = this._CharArray[i]; i++; if (i <= this._CharArray.Length) { node = new GLNode<char>(); switch (t) { case '(': node.Type = NodeType.List; node.Item = Create(); break; case ')': node = null; break; default: node.Type = NodeType.Atom; node.Item = t; break; } } else { return CreateReturn(node); } if (i == this._CharArray.Length) return CreateReturn(node); t = this._CharArray[i++];// For Next. if (node != null) { switch (t) { case ',': node.Next = Create(); break; default: node.Next = null; break; } } return CreateReturn(node); } private GLNode<char> CreateReturn(GLNode<char> node) { return this._Root = node; }
获取广义表深度
若遇到子表则向下探测(深度+1),并与父表(根)的最大深度比较,取大值
public int GetDepth() { return GetDepth(_Root); } public int GetDepth(GLNode<char> node) { int max, depth; if (node == null) return 1; if (node.Next == null && node.Item == null) return 1; for (max = 0; node != null; node = node.Next) { if (node.Type == NodeType.List) { depth = GetDepth((GLNode<char>)node.Item); if (depth > max) max = depth; } } return max + 1; }
输出广义表
public string Write() { return this.Write(this._Root); } public string Write(GLNode<char> node) { StringBuilder sb = new StringBuilder(); switch (node.Type) { case NodeType.Atom: sb.AppendFormat("{0}", node.Item.ToString()); break; case NodeType.List: sb.Append('('); if (node.Item != null) sb.Append(Write((GLNode<char>)node.Item)); sb.Append(')'); break; } if (node.Next != null) { sb.Append(","); sb.Append(Write(node.Next)); } return sb.ToString(); }
以上主要用到了递归的方法.也可以将递归的方法写在GLNode里面,让其自身调用输出方法,这样理解起来更好理解
求表头和表尾
如果同用一个引用地址的话,就非常简单,表头就是第一个元素,剩下的就是表尾了.
否则的话就需要拷贝其中的的数据,同样还是递归
public GLNode<char> GetHead(GLNode<char> node) { if (IsEmpty(node)) return null; var item = new GLNode<char>(); item.Type = node.Type; item.Item = node.Item; return item; } public GLNode<char> GetTail(GLNode<char> node) { if (IsEmpty(node)) return null; var temp = new GLNode<char>(); return temp = Copy(node.Next); } public GLNode<char> Copy(GLNode<char> node) { GLNode<char> temp = null; if (node != null) { temp = new GLNode<char>(); temp.Type = node.Type; switch (temp.Type) { case NodeType.Atom: temp.Item = node.Item; break; case NodeType.List: temp.Item = Copy((GLNode<char>)node.Item); break; } temp.Next = Copy(node.Next); } return temp; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
2010-01-22 MFC笔记(2)菜单