题目要求

广义表的应用

【任务】由于广义表在结构上较线性表复杂得多,因此、广义表的运算也不如线性表简单。本设计要求实现的广义表的建立、查找、输出、取表头和取表尾以及求深度、求逆表等。

【功能要求】设计一个主控菜单,控制6个子系统的运行

1)建立广义表

2)输出广义表

3)结点的查找

4)求广义表表头

5)求广义表表尾

6)求广义表的深度

题目设计过程

需求分析

完成广义表的生成,查找,输出,取表头表尾,求深度并设计可视化界面呈现广义表的上述变化

  • 输入的形式和输入值的范围:生成广义表需要输入的广义表合法,例如(A,B,(C)),查找广义表需要输入字符或字符串,在所有输入中,元素都应该合法
  • 输出的形式:在所有的六种操作后都将结果正确显示在文本框中,不合法操作将输出错误弹窗
  • 实现功能:完成广义表的生成,查找,输出,取表头表尾
  • 测试数据:在建表操作中依次输入(A,B,C),(A,(B,C)),((A),B,C),观察任意功能的结果

概要设计

为了实现上述功能,需要定义数据结构

  • 数据结构模块-广义表(Model层)

    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
    GLNode
    {
    数据对象:D={ai|ai∈object}
    数据关系:R={<ai,ai+1>|ai,ai+1 ∈ D}
    }

    基本操作:
    GLNode<char> Create()
    操作结果:创建广义表
    string Write()
    操作结果:输出广义表
    int GetDepth(GLNode<char> node
    操作结果:获取广义表的深度
    int GetLength(GLNode<char>node)
    操作结果:获取广义表的长度
    string fuckHeads(string item)
    操作结果:获取广义表的头
    string fuckTails(string item)
    操作结果:获取广义表的尾
    GLNode<char> Reverse(GLNode<char> node)
    操作结果:转置广义表
    GLNode<char> Append(GLNode<char> head, GLNode<char> tail)
    操作结果:广义表增添节点
    GLNode<char> Copy(GLNode<char> node)
    操作结果:复制广义表
    bool findKey(string item,string find)
    操作结果:查找目标节点
    bool IsEmpty(GLNode<char> node)
    操作结果:广义表空判断
    bool Verify(string item)
    操作结果:广义表的合法判断
  • View-Model层

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    void ToCreateGL(object sender, RoutedEventArgs e)
    操作结果:在文本框显示建立广义表的提示语句
    void ToOutGL(object sender, RoutedEventArgs e)
    操作结果:在文本框显示输出广义表的提示语句
    void ToFindNodeGL(object sender, RoutedEventArgs e)
    操作结果:在文本框显示寻找节点广义表的提示语句
    void ToFindHeadGL(object sender, RoutedEventArgs e)
    操作结果:在文本框显示寻找广义表头的提示语句
    void ToFindTail(object sender, RoutedEventArgs e)
    操作结果:在文本框显示寻找广义表尾的提示语句
    void ToOutDepth(object sender, RoutedEventArgs e)
    操作结果:在文本框显示输出广义表深度的提示语句
    void AllDoButton(object sender, RoutedEventArgs e)
    操作结果: 根据选择的功能,更新文本框内的输出

  • 主函数模块
1
2
MainWindow()
操作结果:初始化,显示界面

详细设计

  • 定义广义表类

    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
     //节点标识
    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.

    public GLNode()
    { this.Next = null; }
    }

    //广义表定义
    public class GL
    {
    public GLNode<char> _Root;//关键节点
    private char[] _CharArray;//广义表字符
    private int i = 0;//递归标识

    public GL(string item)
    { this._CharArray = item.ToCharArray(); }

    public int Depth
    {
    //调用获取深度函数直接获取深度
    }

    #region 广义表的建立
    public GLNode<char> Create()
    {
    //根据GL的charArray来递归建立广义表
    //从charArray的第一个字符开始,遇到“(”则更新节点的标识(标识为0为普通字符元素,标识为1为表)则递归调用creat()函数,遇到普通字符元素则直接更新节点标识,节点内容储存该值
    }
    #endregion

    #region 广义表的输出
    public string Write()
    {
    return this.Write(this._Root);
    }
    public string Write(GLNode<char> node)
    {
    //创建StringBuilder实例sb来储存结果
    //依次匹配节点标识,当节点type为普通字符则直接添加到sb中,当type为list则先添加“(”到sb中,再调用write()方法来对list进行上述操作并添加“)”到sb中
    //返回结果sb
    }
    #endregion

    #region 广义表的深度
    public int GetDepth(GLNode<char> node)
    {
    //深度的求法是每个元素的括号匹配数加1的最大值
    }
    #endregion

    #region 广义表的长度
    public int GetLength(GLNode<char>node)
    {
    //长度的求法是最大括号中的逗号数加1
    }
    #endregion

    #region 广义表的转置
    public GLNode<char> Reverse(GLNode<char> node)
    {
    //GL节点为空则返回空值
    //匹配节点的标识,当节点标识是普通元素字符时,调用Append()函数在广义表尾后添加头节点
    //当节点标识是list时,调用Append()函数在表尾后添加新node,新node的内容需要再调用reverse()函数来得到

    }
    #endregion

    #region 广义表增加节点
    public GLNode<char> Append(GLNode<char> head, GLNode<char> tail)
    {
    //node为空直接返回需要增加的tail节点
    //返回倒置的GLNode节点
    //节点不空,则一直遍历到尾,知道添加tail节点

    }
    #endregion

    #region 广义表获取表头
    public GLNode<char> GetHead(GLNode<char> node)
    {
    //node为空则返回空
    //直接返回node的item值
    }
    #endregion

    #region 广义表获取表尾

    public GLNode<char> GetTail(GLNode<char> node)
    {
    //node为空则返回空
    //除去头就是尾
    }
    #endregion

    #region 广义表复制
    public GLNode<char> Copy(GLNode<char> node)
    {
    //匹配节点的标识,当节点标识是普通元素字符时,直接将其存储在item中
    //当节点标识是list时,再调用copy()方法
    //最终返回复制的node

    }
    #endregion

    #region 广义表空判断
    public bool IsEmpty(GLNode<char> node)
    { //node为空返回true }

    #endregion

    #region 广义表合法判断
    public bool Verify(string item)
    {
    //遍历GL的广义表的字符,记录左括号,右括号,逗号,普通字符
    //当左括号不等于右括号则为不合法
    //当左括号为0也不合法
    ////当逗号数+1不等于普通字符数时也不合法

    }
    #endregion

    #region 奇怪的表头尾输出
    //像狗屎一样的遍历括号找头尾的方法
    public string fuckHeads(string item)
    {
    //像狗屎一样的遍历括号找头尾的方法
    }
    #endregion

    #region 省事的表尾输出
    public string fuckTails(string item)
    {
    //去掉广义表头就是广义表尾
    }
    #endregion

    #region 查找目标节点
    public bool findKey(string item,string find)
    {
    //在GL字符串中查找目标字符find
    //若存在则返回true,否则返回false
    }
    #endregion
    }

  • 主函数定义

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    class MainWindow : MetroWindow, INotifyPropertyChanged
    {


    private string _AllPut=string.Empty;
    public string AllPut //全部展示在文本框的数据都是它
    {
    get { return _AllPut; }
    set
    {
    _AllPut = value;
    OnPropertyChanged("AllPut");
    }
    }
    public bool CanDo { get; set; } //可操作标识,主要用来判断所有操作是否先创表
    public int Flag { get; set; }//用于简陋的区分各类事件
    public GL myGL { get; set; }//存储广义表
    }
  • 交互

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21

    //更新flag和allput值
    private void ToCreateGL(object sender, RoutedEventArgs e)
    private void ToOutGL(object sender, RoutedEventArgs e)
    private void ToFindNodeGL(object sender, RoutedEventArgs e)
    private void ToFindHeadGL(object sender, RoutedEventArgs e)
    private void ToFindTail(object sender, RoutedEventArgs e)
    private void ToOutDepth(object sender, RoutedEventArgs e)

    //实现确定按钮的功能
    private void AllDoButton(object sender, RoutedEventArgs e)
    {
    //当选择的功能为创表时,先判断文本框输入是否为空,若不为空则判断输入的广义表是否合法,若不合法,则弹出错误提示框,若正确则建立广义表,并更新可操作标识为true
    //若可操作标识为true,且表不空则进行下列操作
    //若选择的功能是输出广义表时,调用write()方法更新allput的值,并显示在文本框
    //当选择的功能是寻找元素时,调用findkey()方法,若该元素存在,则更新allput值为“该元素存在”,并显示在文本框中,若不存在,则显示“该元素不存在”
    //当选择的功能是输出表头时,调用fuckHeads()方法,更新allput值为广义表的头,并显示在文本框
    //当选择的功能是输出表尾,调用fuckTails()方法,更新allput值为广义表的尾,并显示在文本框
    //当选择的功能是输出深度,调用depth()方法,更新allput值为广义表的深度,并显示在文本框

    }
  • 前端设计Xaml

    fuckl

编程设计

  • 后端设计

    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
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    namespace Model
    {
    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.

    public GLNode()
    { this.Next = null; }
    }

    public class GL
    {
    public GLNode<char> _Root;
    private char[] _CharArray;
    private int i = 0;//for create GLNode by recursion.

    public GL(string item) { this._CharArray = item.ToCharArray(); }

    public int Depth
    {
    get
    {
    return GetDepth(this._Root);
    }
    }

    #region 广义表的建立
    public GLNode<char> Create()
    {
    GLNode<char> node = null;

    char t = this._CharArray[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; }
    #endregion


    #region 广义表的输出

    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();
    }
    #endregion

    #region 广义表的深度
    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;
    }
    #endregion

    #region 广义表的长度
    public int GetLength(GLNode<char>node)
    {
    int length=1;
    if (node == null) return 1;
    else
    {
    while(node.Next!=null)
    {
    length++;
    node = node.Next;
    }
    }
    return length;
    }
    #endregion

    #region 广义表的转置
    public GLNode<char> Reverse(GLNode<char> node)
    {
    if (IsEmpty(node)) return null;

    switch (node.Type)
    {
    case NodeType.Atom:
    if (node.Next != null)
    node = Append(Reverse(GetTail(node)), GetHead(node));
    break;
    case NodeType.List:
    node = Append(Reverse(GetTail(node)), new GLNode<char>() { Item = Reverse((GLNode<char>)node.Item), Type = NodeType.List });
    break;
    }

    return node;
    }
    #endregion

    #region 广义表增加节点
    public GLNode<char> Append(GLNode<char> head, GLNode<char> tail)
    {
    if (IsEmpty(head)) return tail;

    var pre = head;
    var cur = head.Next;

    while (cur != null)
    {
    pre = cur;
    cur = cur.Next;
    }

    pre.Next = tail;

    return head;
    }
    #endregion

    #region 广义表获取表头
    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;
    }
    #endregion

    #region 广义表获取表尾

    public GLNode<char> GetTail(GLNode<char> node)
    {
    if (IsEmpty(node)) return null;

    var temp = new GLNode<char>();
    return temp = Copy(node.Next);
    }
    #endregion

    #region 广义表复制
    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;
    }
    #endregion

    #region 广义表空判断
    public bool IsEmpty(GLNode<char> node)
    { return node == null; }

    #endregion

    #region 广义表合法判断
    public bool Verify(string item)
    {
    int commaNum = 0;
    int charNum = 0;
    int leftMarkNum = 0;
    int rightMarkNum = 0;

    foreach (char ch in item.ToCharArray())
    {
    switch (ch)
    {
    case '(':
    leftMarkNum++;
    break;
    case ')':
    rightMarkNum++;
    break;
    case ',':
    commaNum++;
    break;
    default:
    charNum++;
    break;
    }
    }

    if (leftMarkNum != rightMarkNum) return false;
    if(leftMarkNum==0)return false;
    if (commaNum != 0)
    if (commaNum + 1 != charNum) return false;

    return true;
    }
    #endregion

    #region 奇怪的表头尾输出
    //像狗屎一样的遍历括号找头尾的方法
    public string fuckHeads(string item)
    {
    int commaNum = 0;
    int leftMarkNum = 0;
    int rightMarkNum = 0;
    StringBuilder sb = new StringBuilder();

    int flag = 0;
    foreach (char ch in item.ToCharArray())
    {
    Console.WriteLine(ch);
    if (flag != 2)
    {
    Console.WriteLine(ch);
    switch (ch)
    {
    case '(':
    leftMarkNum++;
    if (flag != 0)
    {
    sb.Append(ch);
    }
    break;

    case ')':
    rightMarkNum++;
    sb.Append(ch);
    break;
    case ',':
    commaNum++;
    sb.Append(ch);
    break;
    default:
    sb.Append(ch);
    break;
    }
    if (leftMarkNum - rightMarkNum == 1)
    {
    flag += 1;
    }
    }



    }

    string fuckTail = item;
    return sb.ToString();
    }
    #endregion

    #region 省事的表尾输出
    public string fuckTails(string item)
    {
    int commaNum = 0;
    int leftMarkNum = 0;
    int rightMarkNum = 0;
    StringBuilder sb = new StringBuilder();

    int flag = 0;
    foreach (char ch in item.ToCharArray())
    {
    Console.WriteLine(ch);
    if (flag != 2)
    {
    Console.WriteLine(ch);
    switch (ch)
    {
    case '(':
    leftMarkNum++;
    if (flag != 0)
    {
    sb.Append(ch);
    }
    break;

    case ')':
    rightMarkNum++;
    sb.Append(ch);
    break;
    case ',':
    commaNum++;
    sb.Append(ch);
    break;
    default:
    sb.Append(ch);
    break;
    }
    if (leftMarkNum - rightMarkNum == 1)
    {
    flag += 1;
    }
    }



    }
    Console.WriteLine($"POK:{sb}");

    string fuckTail = item;

    //去掉广义表头就是广义表尾
    fuckTail = fuckTail.Replace(sb.ToString() + ",", "");
    return fuckTail;
    }
    #endregion

    #region 查找目标节点
    public bool findKey(string item,string find)
    {
    GLNode<char> temp=new GLNode<char>();

    if (item.Contains(find)) return true;
    else return false;
    }
    #endregion
    }
    }
  • 交互

    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
    namespace GeneralizedListDesign
    {
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : MetroWindow, INotifyPropertyChanged
    {

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string name)
    {
    PropertyChangedEventHandler handler = PropertyChanged;
    if (handler != null)
    {
    handler(this, new PropertyChangedEventArgs(name));
    }
    }

    private string _AllPut=string.Empty;

    public string AllPut
    {
    get { return _AllPut; }
    set
    {
    _AllPut = value;
    OnPropertyChanged("AllPut");
    }
    }

    private string _AllOut=string.Empty;

    public string AllOut
    {
    get { return _AllOut; }
    set
    {
    _AllOut = value;
    OnPropertyChanged("AllOut");
    }
    }
    public bool CanDo { get; set; }
    public int Flag { get; set; }
    public GL myGL { get; set; }
    private void ToCreateGL(object sender, RoutedEventArgs e)
    {
    Flag = 1;
    CanDo = false;
    AllPut = "请输入合法的广义表例如(A,B,(C))";
    }

    private void ToOutGL(object sender, RoutedEventArgs e)
    {
    Flag = 2;
    AllPut = "是否输出广义表";
    }

    private void ToFindNodeGL(object sender, RoutedEventArgs e)
    {
    Flag = 3;
    AllPut = "请输入要寻找的元素";
    }

    private void ToFindHeadGL(object sender, RoutedEventArgs e)
    {
    Flag = 4;
    AllPut = "是否查找表头";
    }

    private void ToFindTail(object sender, RoutedEventArgs e)
    {
    Flag = 5;
    AllPut = "是否查找表尾";
    }

    private void ToOutDepth(object sender, RoutedEventArgs e)
    {
    Flag = 6;
    AllPut = "是否输出深度";
    }

    private void AllDoButton(object sender, RoutedEventArgs e)
    {
    if (Flag == 1)
    {
    if (AllPut != null)
    {
    myGL = new GL(AllPut);
    if (myGL.Verify(AllPut))
    {
    myGL.Create();
    CanDo = true;
    }
    else
    {
    AllPut = string.Empty;
    AduMessageBox.Show("输入的广义表不合法,请重新选择功能");
    }
    }
    }
    if (!myGL.IsEmpty(myGL._Root) && CanDo)
    {
    if (Flag == 2)
    {
    AllPut = "广义表为:\n"+myGL.Write(myGL._Root);
    }

    if (Flag == 3)
    {
    string temp = myGL.Write(myGL._Root);
    if (temp.Contains(AllPut))
    {
    AllPut = "该元素存在";
    }
    }

    if (Flag == 4)
    {

    AllPut = "广义表表头为:\n" + myGL.fuckHeads(myGL.Write(myGL._Root));
    }

    if (Flag == 5)
    {
    AllPut = "广义表表尾为:\n"+myGL.fuckTails(myGL.Write(myGL._Root));
    }

    if (Flag == 6)
    {
    AllPut = "深度为" + myGL.Depth;
    }
    }
    }


    public MainWindow()
    {
    InitializeComponent();
    this.DataContext = this;
    }


    }
    }
  • 前端设计

    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
    <AduSkin:MetroWindow
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:AduSkin="clr-namespace:AduSkin.Controls.Metro;assembly=AduSkin"
    xmlns:local="clr-namespace:GeneralizedListDesign"
    xmlns:Model="clr-namespace:Model;assembly=Model" x:Class="GeneralizedListDesign.MainWindow"
    mc:Ignorable="d"
    Title="MainWindow" Height="600" Width="800">
    <Grid ShowGridLines="True">
    <Grid.ColumnDefinitions>
    <ColumnDefinition Width="200"/>
    <ColumnDefinition Width=" Auto"/>
    <ColumnDefinition />
    </Grid.ColumnDefinitions>

    <Grid Grid.Column="0" VerticalAlignment="Stretch">
    <Grid.RowDefinitions>
    <RowDefinition/>
    <RowDefinition/>
    <RowDefinition/>
    <RowDefinition/>
    <RowDefinition/>
    <RowDefinition/>
    </Grid.RowDefinitions>

    <AduSkin:MetroButton Margin="3" Grid.Row="0" Click="ToCreateGL" Background="#FFEE796F" >
    <AduSkin:MetroButton.BorderBrush>
    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
    <GradientStop Color="Black"/>
    <GradientStop Color="White" Offset="1"/>
    </LinearGradientBrush>
    </AduSkin:MetroButton.BorderBrush>
    <TextBlock Foreground="Black" FontSize="35" FontFamily="SimHei" HorizontalAlignment="Center" VerticalAlignment="Top"><Run Text="创建广义表"/></TextBlock>
    </AduSkin:MetroButton>

    <AduSkin:MetroButton Margin="3" Grid.Row="1" Click="ToOutGL">
    <TextBlock Foreground="Black" FontSize="35" FontFamily="SimHei" HorizontalAlignment="Center" VerticalAlignment="Top"><Run Text="输出广义表"/></TextBlock>
    </AduSkin:MetroButton>

    <AduSkin:MetroButton Margin="3" Grid.Row="2" Click="ToFindNodeGL">
    <TextBlock Foreground="Black" FontSize="35" FontFamily="SimHei" HorizontalAlignment="Center" VerticalAlignment="Top"><Run Text="查找节点"/></TextBlock>
    </AduSkin:MetroButton>

    <AduSkin:MetroButton Margin="3" Grid.Row="3" Click="ToFindHeadGL">
    <TextBlock Foreground="Black" FontSize="35" FontFamily="SimHei" HorizontalAlignment="Center" VerticalAlignment="Top"><Run Text="查找表头"/></TextBlock>
    </AduSkin:MetroButton>

    <AduSkin:MetroButton Margin="3" Grid.Row="4" Click="ToFindTail">
    <TextBlock Foreground="Black" FontSize="35" FontFamily="SimHei" HorizontalAlignment="Center" VerticalAlignment="Top"><Run Text="查找表尾"/></TextBlock>
    </AduSkin:MetroButton>

    <AduSkin:MetroButton Margin="3" Grid.Row="5" Click="ToOutDepth">
    <TextBlock Foreground="Black" FontSize="35" FontFamily="SimHei" HorizontalAlignment="Center" VerticalAlignment="Top"><Run Text="输出深度"/></TextBlock>
    </AduSkin:MetroButton>


    </Grid>

    <GridSplitter Grid.Column="1" Width="3" HorizontalAlignment="Center" VerticalAlignment="Stretch" ShowsPreview="False"/>

    <Grid Grid.Column="2" Cursor="Hand">
    <Grid.RowDefinitions>
    <RowDefinition />
    <RowDefinition Height=" Auto"/>
    <RowDefinition/>
    </Grid.RowDefinitions>





    <TextBox x:Name="输入处" Text="{Binding AllPut, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MainWindow}}, UpdateSourceTrigger=PropertyChanged}" Grid.Row="1" Margin="148,45,148,145" Height="100" Width="300" FontSize="28" FontFamily="SimHei" HorizontalAlignment="Center" VerticalAlignment="Top" BorderBrush="#FFEE796F" BorderThickness="10,7,10,10" TextWrapping="WrapWithOverflow" />


    <AduSkin:MetroButton Margin="198,210,198,0" Grid.Row="1" Click="AllDoButton" Height="80" Width="200">
    <TextBlock Foreground="Black" FontSize="35" FontFamily="SimHei" HorizontalAlignment="Center" VerticalAlignment="Top"><Run Text="确定"/></TextBlock>
    </AduSkin:MetroButton>


    <GridSplitter Grid.Row="1" Height="3" VerticalAlignment="Center" HorizontalAlignment="Stretch" ShowsPreview="False"/>
    </Grid>
    <Canvas Grid.Column="2" Margin="0,0,0,426" Background="#FFE0AAAA"/>



    </Grid>
    </AduSkin:MetroWindow>

测试结果

fuck1

fuck2

fuck3

fuck4

fuck5

问题和讨论

  • WPF- textbox数据绑定的问题:解决方法:设置属性UpdateSourceTrigger=PropertyChanged,Mode=TwoWay

  • WPF-dataContact无法找到绑定数据(主函数直接定义的属性)的问题:解决方法:设置属性 RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MainWindow}

  • 广义表深度的求法:解决办法:每个元素的括号匹配数加1的最大值

  • 广义表长度的求法:长度的求法为最大括号中的逗号数加1

实训的总结和体会

​ 在本次数据结构广义表的实训中,我们使用C#语言和WPF框架实现了广义表的基本功能,并且为广义表添加了可视化界面。通过这次实训,我对数据结构广义表有了更深入的了解,并且掌握了使用C#语言和WPF框架实现广义表的方法。

​ 在实训中,我们首先学习了广义表的定义和基本操作。广义表是一种扩展了线性表的数据结构,它可以包含其他广义表作为其元素,从而形成了一个多层次的结构。广义表的基本操作包括创建广义表,查找元素,查找表头表尾等。

​ 在实现广义表的基本功能和可视化界面时,我们首先设计了广义表的数据结构,同样使用链表来表示广义表。然后,我们使用C#语言和WPF框架实现了广义表的创建,查找表头表尾操作,并且计划设计了一个可视化界面来展示广义表的结构和操作。

​ 但在实训过程中,我遇到了一些困难和问题。其中一个困难是如何将广义表的结构可视化展示出来。由于广义表可以包含其他广义表,所以在展示广义表的结构时,我需要考虑如何递归地遍历广义表的每个节点,并将其展示在界面上。为了解决这个问题,我使用了递归的方法,在遍历广义表节点时,递归地调用展示函数,并且使用WPF框架的布局控件来展示广义表的结构,但还是遇到了奇怪问题,时间有限最终只能放弃,这倒是我比较遗憾的地方,还有比较折腾的是wpf数据绑定的问题,因为设计是需要双向绑定的,但是按照微软的说明文档(看得比较玄),当我的后台数据更新时前台居然没有显示,于是乎在网上四处搜索,一个比一个玄乎,且毫无作用,有的似乎正确但是又出现了别的问题,最后临机一动直接用blend进行数据绑定,成功发现其实是父类的问题,问题解决。

​ 通过这次实训,我不仅学到了广义表的基本概念和操作,还提高了我的编程能力,并且学会了使用WPF框架实现可视化界面,之前可能winform用的比较多(大一倒是有去使用,大二不知道在干嘛),当然也是比较简陋的使用。在实现广义表的过程中,我需要考虑如何设计数据结构、如何处理特殊情况以及如何展示广义表的结构等,这对我的编程能力提出了一定的要求。同时,我也学会了使用WPF框架来实现简单的可视化界面。

​ 总的来说,这次数据结构广义表的实训让我对广义表有了更深入的了解,掌握了使用C#语言和WPF框架实现广义表的方法,并且实现了可视化界面。通过实践,我提高了我的编程能力,并且对数据结构和界面设计有了更深入的理解。我相信这次实训对我的学习和工作都有很大的帮助。