zoukankan      html  css  js  c++  java
  • 广义表(1)

    参考: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);
        }
    }
     
    (4)有返回值的递归
    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

    子表创建规则:

    1. 若遇左括号(则创建子表
    2. 若遇到右括号则子表结束
    3. 其他状况则认为是一个原子

    即除了元素之外有三种符号(),,

    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;
    }
  • 相关阅读:
    嵌入式Linux基础知识
    面向对象程序设计与原则
    设计模式之工厂模式
    设计模式之单例模式
    基于Doxygen的C/C++注释原则
    设计模式概论
    重启博客
    java 单例模式的几种写法
    CountDownLatch、CyclicBarrier
    java ConcurrentHashMap和CopyOnWriteArrayList解决并发问题
  • 原文地址:https://www.cnblogs.com/Clingingboy/p/1942005.html
Copyright © 2011-2022 走看看