minic 符号表
#include <stdio.h>
#include <string.h>
#include <malloc.h>
typedef struct _array_description
{
int array_size;//代表当前层的最高索引,即上界
struct _array_description* next;//代表下一级
}array_description,*parray_description;
//注意我们把最低层的放在最前面,这样有利于下标的处理 typedef struct _basic_type_pattern
{
char* faction_name;//代表类型名字
int pointer_layer;//代表指针的级数,我们限制为8级,即只占一个字节,其他三个字节以后再使用,先留着
parray_description array_layer;//这里是数组描述,以链表串起多级数组
char* pattern_name;//代表分量的类型
}basic_type_pattern,*pbasic_type_pattern;
typedef struct _composition_list//这个是复合结构的产生式,包括联合、结构、函数
{
pbasic_type_pattern current;//当前的分量
struct _composition_list* next;//下一个分量的指针
}composition_list,*pcomposition_list;
typedef struct _type_description
{
pcomposition_list current_gen_list;//代表当前的产生式的体,也是函数参数的列表
int type_type;//1为函数,2为结构,3为联合,4为基础类型
char* name;//当前类型的名字
void* function_zone;//这个代表了函数相关的域,其中有三个域,类型链表,变量链表,动作链表
//这三个域都是需要后面定义的类型,所以我们目前把他作为一个void类型的指针来处理
int return_pointer ;//代表返回值的指针层数
char* return_name;//代表返回值的类型
}type_description,*ptype_description;//类型声明的体
typedef struct _type_avl_tree
{
struct _type_description* current_type_body;//产生体链表的头节点
//因为有交叉引用。。。
int tree_depth;//当前树的高度,这个域是用来计算平衡因子的
struct _type_avl_tree* left;//左子树
struct _type_avl_tree* right;//右子树
}type_avl_tree,*ptype_avl_tree;//这里是整个的类型avl树 ptype_avl_tree type_tree_head=NULL;//先初始化为空
ptype_avl_tree tree_node_stack[];//这个栈是为了插入和删除用的,以及用来平衡树高
//前面的结构都是对应于类型符号表的,采取的是avl
//下面开始介绍变量符号表,采取的是hash
//对于变量符号表,我们首先需要考虑一个变量所包括的域,其实这些域在定义类型符号表的时候都使用过了
//即basic_type_pattern这个结构体,已经有我们所需要的所有的东西,对于hash值一样的变量,我们通过一个链表串接起来
//而这个链表结构我们现在都有了
//现在我们唯一需要的就是hash表的空间以及hash的方法,这里我们分配400个表项,因为397刚好是质数
//hash函数我们直接采用累加法,最简单的
typedef struct _var_hash_node
{
char* var_name;
int pointer_layer;//代表指针的级数,我们限制为8级,即只占一个字节,其他三个字节以后再使用,先留着
parray_description array_layer;//这里是数组描述,以链表串起多级数组
struct _type_description* var_type;//代表变量的类型
}var_hash_node,*pvar_hash_node;
typedef struct _var_hash_chain
{
pvar_hash_node current_var;
struct _var_hash_node next_var;
}var_hash_chain,*pvar_hash_chain;
pvar_hash_chain var_hash_table[];//注意我们要在后面把这个全都初始化为空
void generation_free(void* generation_body)//释放生成体链表所占的空间
{
pcomposition_list temp_com_list_before,temp_com_list_after;
pbasic_type_pattern temp_basic_pattern;
parray_description temp_array_layer_before,temp_array_layer_after;
temp_com_list_before=(pcomposition_list)generation_list;//转换一下指针
while(temp_com_list_before!=NULL)
{
temp_com_list_after=temp_com_list_before->next;
temp_basic_pattern=temp_com_list_before->current;
free(temp_basic_pattern->faction_name);
temp_array_layer_before=temp_basic_pattern->array_layer;
while(temp_array_layer_before!=NULL)
{
temp_array_layer_after=temp_array_layer_before->next;
free(temp_array_layer_before);
temp_array_layer_before=temp_array_layer_after;
}//释放所有的数组空间
free(temp_com_list_before);
temp_com_list_before=temp_com_list_after;
}//释放所有的分量
}//现在所有的都释放完成了 void insert_var_hash(pvar_hash_node new_var)//在hash表中插入一个表项
{
int string_hash;
int for_i;
char* current_name;
pvar_hash_chain temp_link;//用来串接链表
current_name=new_var->var_name;
for_i=;
string_hash=;
while(current_name[for_i]!='\0')
{
string_hash+=current_name[for_i];
}
string_hash=string_hash%;//取模
temp_link=malloc(sizeof(struct _var_hash_chain));
temp_link->next_var=var_hash_table[string_hash];
temp_link->current_var=new_var;
var_hash_table[string_hash]=temp_link;
}
void delete_var_hash(char* current_name)//这里其实我们不管具体的name,因为,删除的时候我们是一起删除的
{
int string_hash;
int for_i;
pvar_hash_chain temp_link;//用来串接链表
for_i=;
string_hash=;
while(current_name[for_i]!='\0')
{
string_hash+=current_name[for_i];
}
string_hash=string_hash%;//取模
temp_link=var_hash_table[string_hash]->next_var;
free(var_hash_table[string_hash]);
var_hash_table[string_hash]=temp_link;
} pvar_hash_node search_var_hash(char* current_name)//通过名字来查找变量符号表
{
int string_hash;
int for_i;
pbasic_type_pattern result;
pvar_hash_node temp_link;//用来串接链表
for_i=;
string_hash=;
while(current_name[for_i]!='\0')
{
string_hash+=current_name[for_i];
}
string_hash=string_hash%;//取模
temp_link=var_hash_table[string_hash];
while(temp_link!=NULL)
{
result=temp_link->current_var;
if(strcmp(result,current_name)==)
{
return result;
}
else
{
temp_link=temp_link->next_var;
}
}
return NULL;
} void modify_node_depth(ptype_avl_tree current)//修改节点的高度
//由于这个操作需要做很多判断,不修改成函数的话,其他函数将会很长,所以做成一个函数
{
if(current->left!=NULL)
{
if(current->right!=NULL)
{
current->tree_depth=+(current->left->tree_depth+current->right->tree_depth+)/;
}
else
{
current->tree_depth=+current->left->tree_depth;
}
}
else
{
if(current->right!=NULL)
{
current->tree_depth=+current->right->tree_depth;
}
else
{
current->tree_depth=;
}
}
}
void avl_rotate_left( ptype_avl_tree father, ptype_avl_tree current)//将avl树左旋
{
ptype_avl_tree temp_node_one,temp_node_two,temp_node_three;//这命名碉堡了有木有
if(father==NULL)//如果旋转的是头节点
{
temp_node_one=current->right;
type_tree_head=current->right;//修改头节点
temp_node_two=temp_node_one->left;
current->right=temp_node_two;
type_tree_head->left=current;
//至此节点之间的关系修改完毕
//现在开始修改两个节点的高度
modify_node_depth(current);//修改高度有先后顺序的,先修改下面的,后修改上面的
modify_node_depth(temp_node_one)
}
else
{
temp_node_one=current->right;
current->right=temp_node_one->left;
temp_node_one->left=current;
if(father->left==current)
{
father->left=temp_node_one;
}
else
{
father->right=temp_node_one;
}
modify_node_depth(current);
modify_node_depth(temp_node_one);
mpdify_node_depth(father);
//这里需要修改三个节点
}
}
void avl_rotate_right(ptype_avl_tree father, ptype_avl_tree current)//右旋节点
{
ptype_avl_tree temp_node_one,temp_node_two,temp_node_three;//这命名碉堡了有木有
if(father==NULL)//如果旋转的是头节点
{
temp_node_one=current->left;
type_tree_head=current->left;//修改头节点
temp_node_two=temp_node_one->right;
current->left=temp_node_two;
type_tree_head->right=current;
//至此节点之间的关系修改完毕
//现在开始修改两个节点的高度
modify_node_depth(current);//修改高度有先后顺序的,先修改下面的,后修改上面的
modify_node_depth(temp_node_one)
}
else
{
temp_node_one=current->left;
current->left=temp_node_one->right;
temp_node_one->right=current;
if(father->right==current)
{
father->right=temp_node_one;
}
else
{
father->left=temp_node_one;
}
modify_node_depth(current);
modify_node_depth(temp_node_one);
mpdify_node_depth(father);
//这里需要修改三个节点
}
} void insert_avl_node(ptype_description new_type_node)//插入一个新的节点
{
ptype_avl_tree temp_node_one,temp_node_two,temp_node_three,new_node;
ptype_description temp_type_description;
int stack_pointer=;
int compare_result=;//这个变量会被复用,在插入时作为字符串比较的结果,在平衡时作为高度差。
int original_depth;//这个用来记录节点原来的高度
tree_node_stack[]=NULL;//哨兵节点,在旋转的时候有用
new_node=malloc(sizeof(struct _type_avl_tree));
new_node->current_gen_list=new_type_node;
new_node->left=NULL;
new_node->right=NULL;
new_node->tree_depth=;
if(type_tree_head==NULL)
{
type_tree_head=new_node;
return ;
}
else
{
temp_node_one=type_tree_head;
while(temp_node_one!=NULL)
{
stack_pointer++;
tree_node_stack[stack_pointer]=temp_node_one;
temp_type_description=(ptype_description)temp_node_one->current_type_body;
compare_result=strcmp(new_type_node->name,temp_type_description->name);
if(compare_result<)
{
temp_node_one=temp_node_one->left;
}
else
{
temp_node_one=temp_node_one->right;
}
}//这个栈记录了插入所经过的路径
temp_node_one=tree_node_stack[stack_pointer];
if(compare_result<)
{
temp_node_one->left=new_node;
}
else
{
temp_node_one->right=new_node;
}
//现在节点关系已经建立了,开始平衡树高度了
while(stack_pointer>)//遍历整个栈,来寻找需要平衡的节点
//注意,这里跳出循环的条件是,某个节点在修改后高度没有改变,这样就没有必要再去修改了
//或者启用了平衡操作,启用平衡操作之后可以确保高度没有改变,因此可以退出
{
temp_node_one=tree_node_stack[stack_pointer];
original_depth=temp_node_one->tree_depth;
modify_tree_depth(temp_node_one);
if(original_depth==temp_node_one->tree_depth)
{
return ;
}
else
{
compare_result=temp_node_one->left->tree_depth-temp_node_one->right->tree_depth;
if(compare_result==)//如果左边比右边高2
{
//这个时候需要考虑是要进行两次旋转还是一次旋转
if(tree_node_stack[stack_pointer+]->right==tree_node_stack[stack_pointer+])
//这种情况我们需要做两次旋转
{
avl_rotate_left(tree_node_stack[stack_pointer],tree_node_stack[stack_pointer+]);
}
avl_rotate_right(tree_node_stack[stack_pointer-],tree_node_stack[stack_pointer]);
//第二次旋转
return ;
}
else
{
if(compare_result==-)
{
if(tree_node_stack[stack_pointer+]->left==tree_node_stack[stack_pointer+])
{
avl_rotate_right(tree_node_stack[stack_pointer],tree_node_stack[stack_pointer+]);
}
avl_rotate_left(tree_node_stack[stack_pointer-],tree_node_stack[stack_pointer]);
return ;
}
else
{
//这里继续向上传递
stack_pointer--;
}
}
}
}
//至此所有的插入及平衡都做完了
}
} void delete_avl_node(char* avl_node_name)//这里我们要求已经做过参数检查了,挂了自己撞墙去
{
ptype_avl_tree temp_node_one,temp_node_two,temp_node_three;//神一样的命名方法
ptype_description temp_type_description;
int stack_pointer=;
int compare_result=;
int original_depth=;
temp_node_one=type_tree_head;
tree_node_stack[]=NULL;//哨兵
temp_type_description=(ptype_description)temp_node_one->current_type_body;
compare_result=strcmp(avl_node_name,temp_type_description->name);
while(compare_result!=)
{
stack_pointer++;
tree_node_stack[stack_pointer]=temp_node_one;
if(compare_result>)
{
temp_node_one=temp_node_one->right;
}
else
{
temp_node_one=temp_node_one->left;
}
temp_type_description=(ptype_description)temp_node_one->current_type_body;
compare_result=strcmp(avl_node_name,temp_type_description->name);
}//找到对应的节点
if(temp_node_one->left==NULL||temp_node_one->right==NULL)//如果有删除的节点只有一个或零个子节点
{
if(stack_pointer==)//如果是头节点,且只有不多于1个的子节点
{
type_tree_head=temp_node_one->left|temp_node_one->right;//这里就不需要考虑空节点了,这里已经考虑过了
free(temp_node_one);
return ;//直接返回
}//这里就不需要平衡了
else//如果不是头节点
{
temp_node_two=tree_node_stack[stack_pointer];
if(temp_node_two->left==temp_node_one)
{
temp_node_two->left=temp_node_one->left|temp_node_one->right;
}
else
{
temp_node_two->right=temp_node_one->left|temp_node_one->right;
}//修正好所有的节点关系
}
}
else//有两个子节点,选择后继来处理
{
temp_node_two=temp_node_one->right;
while(temp_node_two!=NULL)
{
stack_pointer++;
tree_node_stack[stack_pointer]=temp_node_two;
temp_node_two=temp_node_two->left;
}
temp_node_two=tree_node_stack[stack_pointer];
temp_node_one->current_generate_body=temp_node_two->current_generate_body;
//这样就把这个节点复制过去了
//现在我们要删除这个新的节点
stack_pointer--;//最后一个点抛弃,因为我们要删除这个点
//现在我们开始修改好节点关系,修改完之后再去平衡
if(temp_node_one->right==temp_node_two)//这个是特殊情况
{
temp_node_one->right=temp_node_two->right;
}
else
{
tree_node_stack[stack_pointer]->left=temp_node_two->right;
}//这里修正好所有的节点关系,然后再开始平衡 }
//现在开始进行平衡
while(stack_pointer>)
{
//这里跳出循环的条件是某个节点的高度没有变化,调用平衡处理之后,还是有可能影响上面的节点
//所以还是需要处理其他的点,因此平衡处理不是跳出循环的条件
temp_node_three=tree_node_stack[stack_pointer];
original_depth=temp_node_three->tree_depth;
modify_node_depth(temp_node_three);
if(temp_node_three->tree_depth==original_depth)
{
//如果子树的高度不变,则不需要继续处理了
return ;
}
else//这里平衡操作不需要做第二次旋转,一次旋转就足够了
{
compare_result=temp_node_three->left->tree_depth-temp_node_three->right->tree_depth;
if(compare_result==)
{
rotate_avl_right(tree_node_stack[stack_pointer-],tree_node_stack[stack_pointer]);
stack_pointer--;
}
else
{
if(compare_result==-)
{
rotate_avl_left(tree_node_stack[stack_pointer-],tree_node_stack[stack_pointer]);
stack_pointer--;
}
else
{
stack_pointer--;
}
}
}
}
return ;
}
ptype_description search_avl_tree(char* target_name)//在当前avl树中寻找是否有相应的名字的节点
{
ptype_avl_tree result;//作为遍历树的指针
ptype_description return_result;//作为返回的节点
int compare_result;//比较的时候的返回结果
result=type_tree_head;
while(result!=NULL)
{
return_result=(ptype_description)result->current_type_body;
compare_result=strcmp(target_name,return_result->name);
if(compare_result==)
{
break;//不需要继续找了
}
else
{
if(compare_result<)
{
result=result->left;
}
else
{
result=result->right;
}
}
}
return return_result;
}
minic 符号表的更多相关文章
- C/C++编译和链接过程详解 (重定向表,导出符号表,未解决符号表)
详解link 有 些人写C/C++(以下假定为C++)程序,对unresolved external link或者duplicated external simbol的错误信息不知所措(因为这样的错 ...
- ELF Format 笔记(七)—— 符号表
最是那一低头的温柔,像一朵水莲花不胜凉风的娇羞,道一声珍重,道一声珍重,那一声珍重里有蜜甜的忧愁 —— 徐志摩 ilocker:关注 Android 安全(新手) QQ: 2597294287 符号表 ...
- IDA 与VC 加载符号表
将Windbg路径下的symsrv.yes 拷贝到ida 的安装目录,重新分析ntoskrnl.exe, 加载本地的符号表 添加环境变量 变量名:_NT_SYMBOL_PATH变量值:SRV*{$P ...
- iOS 符号表恢复 & 逆向支付宝
推荐序 本文介绍了恢复符号表的技巧,并且利用该技巧实现了在 Xcode 中对目标程序下符号断点调试,该技巧可以显著地减少逆向分析时间.在文章的最后,作者以支付宝为例,展示出通过在 UIAlertVie ...
- 使用objdump objcopy查看与修改符号表
使用objdump objcopy查看与修改符号表动态库Linuxgccfunction 我们在 Linux 下运行一个程序,有时会无法启动,报缺少某某库.这时需要查看可执行程序或者动态库中的符 ...
- 符号表(Symbol Tables)
小时候我们都翻过词典,现在接触过电脑的人大多数都会用文字处理软件(例如微软的word,附带拼写检查).拼写检查本身也是一个词典,只不过容量比较小.现实生活中有许多词典的应用: 拼写检查 数据库管理应用 ...
- 符号表实现(Symbol Table Implementations)
符号表的实现有很多方式,下面介绍其中的几种. 乱序(未排序)数组实现 这种情况,不需要改变数组,操作就在这个数组上执行.在最坏的情况下插入,搜索,删除时间复杂度为O(n). 有序(已排序)数组实现 这 ...
- 程序减肥,strip,eu-strip 及其符号表
程序减肥,strip,eu-strip 及其符号表 我们要给我们生成的可执行文件和DSO瘦身,因为这样可以节省更多的磁盘空间,所以我们移除了debug信息,移除了符号表信息,同时我们还希望万一出事了, ...
- 《Algorithms 4th Edition》读书笔记——3.1 符号表(Elementary Symbol Tables)-Ⅳ
3.1.4 无序链表中的顺序查找 符号表中使用的数据结构的一个简单选择是链表,每个结点存储一个键值对,如以下代码所示.get()的实现即为遍历链表,用equals()方法比较需被查找的键和每个节点中的 ...
随机推荐
- python模式匹配,提取指定字段
re匹配时分多行模式(re.M)与单行模式(rs.S),多行模式是每一行单独匹配,单行模式是把所有的行当成一行来匹配. 单行模式下.可以匹配换行符. ^$匹配所有字符 import re s='1_2 ...
- MySQL的数据引擎讲解
一.MySQL的数据引擎讲解 在MySQL数据库中,常用的引擎主要就是2个:Innodb和MyIASM. 1.简单介绍这两种引擎,以及该如何去选择. a.Innodb引擎,Innodb引擎提供了对数据 ...
- CodeForces 779A Pupils Redistribution
简单题. 因为需要连边的人的个数一样,又要保证和一样,所以必须每个数字的个数都是一样的. #include<map> #include<set> #include<cti ...
- POJ2912 Rochambeau [扩展域并查集]
题目传送门 Rochambeau Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 4463 Accepted: 1545 ...
- JZYZOJ1536 [haoi2014]走出金字塔
http://172.20.6.3/Problem_Show.asp?id=1536 确实不难,找规律的题,开始想复杂了,分了好多情况.开始为省几个变量加了一大堆max,min,abs代码一下子复杂太 ...
- 2017icpc 乌鲁木齐网络赛
A .Banana Bananas are the favoured food of monkeys. In the forest, there is a Banana Company that pr ...
- BZOJ 2157 旅游(动态树)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2157 [题目大意] 支持修改边,链上查询最大值最小值总和,以及链上求相反数 [题解] ...
- BZOJ 1828 [Usaco2010 Mar]balloc 农场分配(贪心+线段树)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1828 [题目大意] 现在有一些线段[l,r]的需求需要满足,i位置最多允许a[i]条线 ...
- 【贪心】 Codeforces Round #419 (Div. 1) A. Karen and Game
容易发现,删除的顺序不影响答案. 所以可以随便删. 如果行数大于列数,就先删列:否则先删行. #include<cstdio> #include<algorithm> usin ...
- 【后缀自动机】hihocoder1441 后缀自动机一·基本概念
时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi:今天我们来学习一个强大的字符串处理工具:后缀自动机(Suffix Automaton,简称SAM).对于一个字符串 ...