• 重言式判别


    题目参见:清华大学出版社的《数据结构题集(C语言版)》 P148 5.1

    刚开始时不知道从哪里下手,尤其是将输入的字符串序列建立成二叉树,自己想了半天越想越复杂,于是决定不浪费时间去网上直接找解题思路,发现通过构建加权字符数组的方法很不错,整体思路有了就动手实现吧,整个过程中对递归的应用很多,更加体会到了递归的美妙之处啊。。= v =。

    中间比较纠结的是判别是否永真或永假,尤其是每进行一次运算会改变二叉树中原先的变元,最初没有考虑到这个结果很多都是直接跳到了结果,没有判断过程。。。

    本来以为构造出二叉树之后后面的工作会简单一些,结果还是耗了很长时间。。= =||,高兴太早了麽,,,代码就堆在下面了。。

    代码
    1 #include <stdio.h>
    2 #include <stdlib.h>
    3 #include <string.h>
    4
    5 typedef struct DutyElement
    6 {
    7 char data;
    8 int duty;
    9 }DutyElement;
    10
    11 DutyElement DutyArray[100]; //定义加权数组
    12  
    13 typedef struct BiTNode
    14 {
    15 char data;
    16 struct BiTNode *lchild, *rchild;
    17 }BiTNode, *BiTree;
    18
    19  void InitDutyArray(char *s, int n) //根据输入的序列初始化加权数组
    20  {
    21 int i, j;
    22 for (i = 0; i < n; i++)
    23 {
    24 DutyArray[i].data = s[i];
    25 switch (DutyArray[i].data) //分别赋权值
    26   {
    27 case '~':
    28 DutyArray[i].duty = 3; break;
    29 case '&':
    30 DutyArray[i].duty = 2; break;
    31 case '|':
    32 DutyArray[i].duty = 1; break;
    33 default:
    34 DutyArray[i].duty = 0; break;
    35 }
    36 }
    37 for (i = 0; i < n; i++)
    38 {
    39 if (DutyArray[i].data == '(') //是左括号的话则对运算符进行加权操作
    40   {
    41 for (j = i; j < n; j++)
    42 {
    43 if (DutyArray[j].duty != 0)
    44 DutyArray[j].duty += 5;
    45 }
    46 }
    47 else
    48 {
    49 if (DutyArray[i].data == ')') //右括号的话对运算符进行减权操作
    50   {
    51 for (j = i; j < n; j++)
    52 {
    53 if (DutyArray[j].duty != 0)
    54 DutyArray[j].duty -= 5;
    55 }
    56 }
    57 }
    58 }
    59 }
    60
    61  int SearchMinDutyOperator(int a, int b) //寻找权值最小的运算符,即为二叉树的根节点
    62  {
    63 int i, n = a, duty = 1000;
    64 for (i = a; i < b + 1; i++)
    65 {
    66 if (DutyArray[i].duty > 0 && DutyArray[i].duty < duty)
    67 {
    68 n = i;
    69 duty = DutyArray[i].duty;
    70 }
    71 }
    72 return n;
    73 }
    74
    75  int ParenthesesCloesed(int a, int b) //判断序列是否在最外层有一对括号
    76  {
    77 int i, n = 0;
    78 for (i = a; i <= b; i++)
    79 {
    80 if (DutyArray[i].data == '(')
    81 n++;
    82 if (DutyArray[i].data == ')')
    83 n--;
    84 if (n == 0)
    85 break;
    86 }
    87 if (i == b)
    88 return 1;
    89 else
    90 return 0;
    91 }
    92
    93 BiTree Create(int a, int b) //根据加权数组创建二叉树
    94  {
    95 BiTree p;
    96 if (DutyArray[a].data == '(' && DutyArray[b].data == ')' && ParenthesesCloesed(a, b) == 1) //去括号
    97 {
    98 a += 1;
    99 b -= 1;
    100 }
    101 if (a > b)
    102 p = NULL;
    103 else
    104 {
    105 if (a == b)
    106 {
    107 p = (BiTNode *)malloc(sizeof(BiTNode));
    108 p->data = DutyArray[a].data;
    109 p->lchild = NULL;
    110 p->rchild = NULL;
    111 }
    112 else
    113 {
    114 int n;
    115 n = SearchMinDutyOperator(a, b);
    116 p = (BiTNode *)malloc(sizeof(BiTNode));
    117 p->data = DutyArray[n].data;
    118 p->lchild = Create(a, n - 1);
    119 p->rchild = Create(n + 1, b);
    120 }
    121 }
    122 return p;
    123 }
    124
    125 void AssignValue(BiTree T, char letter, char binary) //递归为对应的字母赋二进制字符
    126 {
    127 if (T)
    128 {
    129 if (T->data == letter)
    130 T->data = binary;
    131 AssignValue(T->lchild, letter, binary);
    132 AssignValue(T->rchild, letter, binary);
    133 }
    134 }
    135
    136 int Calculate(BiTree T) //递归计算二进制字符二叉树
    137 {
    138 switch (T->data)
    139 {
    140 case '0':
    141 return 0;
    142 case '1':
    143 return 1;
    144 case '~':
    145 return !Calculate(T->rchild);
    146 case '&':
    147 return (Calculate(T->lchild) & Calculate(T->rchild));
    148 case '|':
    149 return (Calculate(T->lchild) | Calculate(T->rchild));
    150 }
    151 }
    152
    153 void main()
    154 {
    155 BiTree T;
    156 int m = 0, n, i, j, k, length = 0, strlength, num = 1, flag;
    157 char value[20] = {0};
    158 char s[100] = {0};
    159 char c, *str;
    160 str = (char *)malloc(sizeof(char) * 20);
    161 for (i = 0; i < 20; i++)
    162 {
    163 *(str + i) = 0;
    164 }
    165 c = getchar();
    166 i = 0;
    167 while (c != '\n')
    168 {
    169 if (c != ' ')
    170 {
    171 s[i] = c;
    172 i++;
    173 }
    174 c = getchar();
    175 }
    176 for (i = 0; i < 100; i++)
    177 {
    178 if (s[i] == 0)
    179 {
    180 n = i; //n为输入序列的长度
    181 break;
    182 }
    183 }
    184 for (i = 0; i < n; i++)
    185 {
    186 if (strchr(s, 'A' + i) != NULL)
    187 length++;
    188 else
    189 break;
    190 }
    191 length = i;
    192 InitDutyArray(s, n); //初始化加权数组
    193 T = Create(0, n - 1);
    194 for (i = 0; i < length; i++)
    195 {
    196 AssignValue(T, 'A' + i, '0');
    197 }
    198 flag = Calculate(T);
    199 for (i = 0; i < length; i++)
    200 {
    201 num *= 2;
    202 }
    203 for (i = 0; i < num; i++)
    204 {
    205 T = Create(0, n - 1); //由于每运算一次会将原来的二叉树中的变元改变,所以得重新构造
    206 itoa(i, str, 2);
    207 strlength = strlen(str);
    208 for (j = 0; j < length; j++)
    209 {
    210 if (strlength - j - 1 >= 0)
    211 value[length - j - 1] = *(str + strlength - 1 - j);
    212 else
    213 value[length - j - 1] = '0';
    214
    215 }
    216 for (k = 0; k < length; k++)
    217 {
    218 AssignValue(T, 'A' + k, value[k]);
    219 }
    220 if (Calculate(T) != flag)
    221 {
    222 printf("Satisfactible\n");
    223 break;
    224 }
    225 else
    226 {
    227 if (i == num - 1 && flag == 1)
    228 {
    229 printf("True forever\n");
    230 return;
    231 }
    232 if (i == num - 1 && flag == 0)
    233 {
    234 printf("False forever\n");
    235 return;
    236 }
    237 }
    238 }
    239 for (i = 0; i < length; i++)
    240 {
    241 printf("%c ", 'A' + i);
    242 }
    243 printf("\n");
    244 c = getchar(); //输入对各字符的赋值,保存在value数组中
    245 i = 0;
    246 while (c != ';')
    247 {
    248 if (c != ',')
    249 {
    250 value[i] = c;
    251 i++;
    252 }
    253 c = getchar();
    254 }
    255 T = Create(0, n - 1); //重新构造二叉树
    256 for (i = 0; i < length; i++)
    257 {
    258 AssignValue(T, 'A' + i, value[i]);
    259 }
    260 printf("The result is %d\n", Calculate(T));
    261 }
  • 相关阅读:
    深入学习Make命令和Makefile(上)
    make命令
    ubuntu 重启网络方法--通过杀死进程重启网络
    悟空遥控器 --- 手机投屏到电视 播放视频
    组织结构图 --- 商务
    软件和数据库
    因果图---鱼骨图
    流程图 --- BPMN规范简介
    异次元软件
    Free Download Manager (FDM) 中文版
  • 原文地址:https://www.cnblogs.com/kanone/p/1890065.html
Copyright © 2020-2023  润新知