Add files via upload

master
chinatianyudai 7 years ago committed by GitHub
parent df3da815d4
commit 005c8fc991
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,33 @@
#pragma once
#include"List.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int InitList(LinkList *L)
{
*L = (LinkList)malloc(sizeof(Node_List)); /* 产生头结点,并使L指向此头结点 */
if (!(*L)) /* 存储分配失败 */
return 0;
(*L)->next = NULL; /* 指针域为空 */
return 1;
}
int ListInsert(LinkList *L, int i, int e)
{
int j;
LinkList p, s;
p = *L;
j = 1;
while (p && j < i) /* 寻找第i个结点 */
{
p = p->next;
++j;
}
if (!p || j > i)
return 0; /* 第i个元素不存在 */
s = (LinkList)malloc(sizeof(Node_List)); /* 生成新结点(C语言标准函数) */
s->data = e;
s->next = p->next; /* 将p的后继结点赋值给s的后继 */
p->next = s; /* 将s赋值给p的后继 */
return 1;
}

@ -0,0 +1,9 @@
#pragma once
typedef struct Node_List
{
int data;
struct Node_List *next;
}Node_List;
typedef struct Node_List *LinkList; //¶¨ÒåLinkList
int InitList(LinkList *L);
int ListInsert(LinkList *L, int i, int e);

@ -0,0 +1,115 @@
#pragma once
#include "hashTable.h"
#define MAX_PRIME_LESS_THAN_HASH_LEN 7993
char* strDup(const char* str)
{
int len;
char* ret;
if (str == NULL)return NULL;
len = strlen(str);
ret = (char*)malloc(len + 1);
if (ret != NULL) {
memcpy(ret, str, len);
ret[len] = '\0';
}
return ret;
}
unsigned int hashfunc(char *str, int len)
{
register unsigned int sum = 0;
register unsigned int h = 0;
register char *p = str;
while (p - str < len)
{
register unsigned short a = *(p++);
sum ^= a * (p - str);
h ^= a / (p - str);
}
return ((sum << 16) | h) % MAX_PRIME_LESS_THAN_HASH_LEN;
}
void initHashTable(hashTable* t)
{
int i;
if (t == NULL)return;
for (i = 0; i < BUCKETCOUNT; ++i) {
t->bucket[i].key = NULL;
t->bucket[i].value = NULL;
t->bucket[i].next = NULL;
}
}
void freeHashTable(hashTable* t)
{
int i;
entry* e, *ep;
if (t == NULL)return;
for (i = 0; i<BUCKETCOUNT; ++i) {
e = &(t->bucket[i]);
while (e->next != NULL) {
ep = e->next;
e->next = ep->next;
free(ep->key);
free(ep->value);
free(ep);
}
}
}
int insertEntry(hashTable* t, char *key, RBRoot *value)
{
int index, vlen1, vlen2;
entry* e, *ep;
if (t == NULL || key == NULL || value == NULL) {
return -1;
}
index = hashfunc(key, strlen(key));
if (t->bucket[index].key == NULL) {
t->bucket[index].key = (char *)malloc(strlen(key)*sizeof(char));
t->bucket[index].key = key;
t->bucket[index].value = (RBRoot *)malloc(sizeof(RBRoot));
t->bucket[index].value = value;
}
else {
e = ep = &t->bucket[index];
while (e != NULL) {
if (strcmp(e->key, key) == 0)
{
memcpy(e->value, value, sizeof(RBRoot));
return index;
}
ep = e;
e = e->next;
}
e = (entry*)malloc(sizeof(entry));
e->key = strDup(key);
e->value= (RBRoot *)malloc(sizeof(RBRoot));
e->value = value;
e->next = NULL;
ep->next = e;
}
return index;
}
RBRoot* findValue(hashTable*t, char *key)
{
int index;
entry* e;
if (t == NULL || key == NULL)
{
return NULL;
}
index = hashfunc(key,strlen(key));
e = &(t->bucket[index]);
if (e->key == NULL)return NULL;
while (e != NULL)
{
if (strcmp(key, e->key)==0)
{
return e->value;
}
e = e->next;
}
return NULL;
}

@ -0,0 +1,24 @@
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "rbtree.h"
#define BUCKETCOUNT 9000
struct _hash_Entry
{
const char* key;//键
RBRoot* value;//值
struct _hash_Entry* next;//下一个结点
};//结点的内容
typedef struct _hash_Entry entry;
typedef struct _Table
{
entry bucket[BUCKETCOUNT]; //定义桶
}hashTable;
char* strDup(const char* str);
unsigned int hashfunc(char*key, int len);//哈希值的计算
void initHashTable(hashTable* t);//初始化哈希表
void freeHashTable(hashTable* t);//释放哈希表
int insertEntry(hashTable* t, char *key, RBRoot *value);//插入数据
RBRoot* findValue(hashTable*t, char *key);//查找
//entry* removeTable(hashTable*t, char key);//删除,暂时不用

@ -0,0 +1,259 @@
extern "C" {
#include"hashTable.h"
#include"rbtree.h"
#include"List.h"
}
#include<iostream>
#include <fstream>
#include<algorithm>
#include<vector>
#include<string>
#define TRUE 1
#define FALSE 0
using namespace std;
vector<string> stopword; //stopword向量有一些词出现次数太多得不偿失意义不大如 a the
void Insertword(string voc, string filename, int address, hashTable * Index);//建立索引时要插入元素
void BuildIndex(hashTable *Index);// 建立索引
void collect_stopword();//把stopword加入向量
bool isstopword(string W);//判断stopword
string Filename(int N, int M);//用这种方式获取一个文件名
bool isword(char ch);//判断这个char是否合法
void collect_stopword()
{
ifstream fp;
string stop;
char ch;
fp.open("stopword.txt", ios_base::in | ios_base::binary);
if (!fp)
{
cout << "读取屏蔽词出错!" << endl;
return;
}
fp.get(ch);
while (fp)
{
stop = "";
while (!isword(ch) && !fp.eof())
{
fp.get(ch);
}
if (!fp)
break;
while (isword(ch) && !fp.eof())
{
stop += ch;
fp.get(ch);
}
transform(stop.begin(), stop.end(), stop.begin(), tolower);
stopword.push_back(stop);
}
}
//判断是不是stopword——从上一个函数中取得了所有stopword拼成的字符串判断是否能在里面找到就行
bool isstopword(string W)
{
if (find(stopword.begin(), stopword.end(), W) == stopword.end())
return 0;
else
return 1;
}
//判断是否是单词
bool isword(char ch)
{
//标准传入ch在A-Z或者a-z中间或者是\配合n吧就算
int D = ((ch >= 'a' && ch <= 'z') || (ch >= 'A'&& ch <= 'Z') || (ch == '\''));
return ((D == 1) ? TRUE : FALSE);
}
//构造文件名的函数因为示范文件是10xx x的格式所以这么构造
string Filename(int N, int M)
{
string res;
char file[15];
char chap[10];
_itoa_s(N, file, 10);
_itoa_s(M, chap, 10);
strcat_s(file, 15, " ");
strcat_s(file, 15, chap);
strcat_s(file, 15, ".txt");
res = file;
return res;
}
int hashfile(char*p)
{
int i = strlen(p);
int hash=0;
int j;
for (j = 0; j < i; j++)
{
if (p[j] >= '0'&&p[j] <= '9')
{
hash = hash * 10 + p[j] - '0';
}
}
return hash;
}
//整理扫描到的当前单词信息(在哪个文件的哪里),再插入 address标志了单词位置
void Insertword(string voc, string filename, int address, hashTable* t)
{
char p[50];
strcpy(p, voc.c_str());
char *fname = (char*)filename.c_str();
if (findValue(t,p)==NULL)//假如索引里头没有这个词我们就把他加进去
{
LinkList L;
InitList(&L);
ListInsert(&L, 1, address);
RBRoot *root;
root = create_rbtree();
RBleaf *leaf = (RBleaf*)malloc(sizeof(RBleaf));
strcpy(leaf->filename, filename.c_str());
leaf->hashfile = hashfile(fname);
leaf->index = L;
insert_rbtree(root, *leaf);
insertEntry(t, p, root);
//cout << "haha" << endl;
//inorder_rbtree(t->bucket[hashfunc(p,strlen(p))].value);
}
else//有的话就得更新它的数据
{
RBRoot *tempRB=findValue(t, p);
//如果小向量红黑树sour中没有找到当前文件名意思是现在找到的词是本文件中第一次出现
if (rbtree_search(tempRB,hashfile(fname))==NULL)
{
LinkList L;
InitList(&L);
ListInsert(&L, 1, address);
RBleaf *leaf = (RBleaf*)malloc(sizeof(RBleaf));
strcpy(leaf->filename, filename.c_str());
leaf->hashfile = hashfile(fname);
leaf->index = L;
insert_rbtree(tempRB, *leaf);
//inorder_rbtree(t->bucket[hashfunc(p, strlen(p))].value);
//insertEntry(t, p, tempRB);
}
//如果小向量sour中找到了当前文件名意思是现在找到的词在本文件中出现过NA向量已经建立过了直接加就行
else
{
RBleaf*templeaf = rbtree_search(tempRB, hashfile(fname));
ListInsert(&templeaf->index, 1, address);
//inorder_rbtree(t->bucket[hashfunc(p, strlen(p))].value);
}
}
}
void BuildIndex(hashTable *Index)
{
int cou;
int num;
string filename = "";
ifstream fp;
string voc = "";
int address;
char ch;
//这个双层循环是配合Filename函数自己写的完成->读所有文件的任务
for (cou = 1001; cou <= 1042; cou++)
{
for (num = 1; num <= 153; num++)
{
filename = Filename(cou, num);
fp.open("Shakespeare/" + filename, ios_base::in | ios_base::binary);
if (!fp.is_open())
continue;
cout << filename << endl;
address = 0;
fp.get(ch);
while (fp)//以前学过的逐个单词读
{
voc = "";
//不是单词且没到结尾就继续
while (!isword(ch) && !fp.eof())
{
fp.get(ch);
}
//到结尾就退出(去下一个文件)
if (!fp)
break;
//是单词的操作就在String vocabulary中连缀上它
while (isword(ch) && !fp.eof())
{
voc += ch;
fp.get(ch);
}
transform(voc.begin(), voc.end(), voc.begin(), tolower); //转化成小写字母
//下标移动(数在第几个位置嘛)
address++;
//假如不是屏蔽词汇就整理单词信息再插入索引用之前的Insert函数
if (!isstopword(voc))
{
Insertword(voc, filename, address, Index);
//getchar();
}
}
fp.close();
}
}
}
void test() //测试功能专用
{
LinkList L;
InitList(&L);
ListInsert(&L, 1, 10);
ListInsert(&L, 1, 30);
hashTable t;
initHashTable(&t);
RBRoot *root = NULL;
root = create_rbtree();
RBleaf *leaf = (RBleaf*)malloc(sizeof(RBleaf));
//leaf->filename = "hahah";
leaf->hashfile = 20;
leaf->index = L;
insert_rbtree(root, *leaf);
leaf = (RBleaf*)malloc(sizeof(RBleaf));
//leaf->filename = "hahaha";
leaf->hashfile = 10;
leaf->index = L;
insert_rbtree(root, *leaf);
insertEntry(&t, "son", root);
insertEntry(&t, "on", root);
RBRoot *b = findValue(&t, "son");
inorder_rbtree(b);
getchar();
}
int main(){
//test();
hashTable t;
initHashTable(&t);
cout << "屏蔽词载入中..." << endl;
collect_stopword();
cout << "屏蔽词库建立完成" << endl;
cout << "倒排索引建立中..." << endl;
BuildIndex(&t);
cout << "倒排索引建立完成" << endl;
while (1) {
string s;
cin >> s;
char *p = (char *)s.c_str();
inorder_rbtree(t.bucket[hashfunc(p, strlen(p))].value);
}
//inorder_rbtree((RBRoot*)t.bucket[hashfunc(p,strlen(p))].value);
getchar();
getchar();
}

@ -0,0 +1,668 @@
/**
* C(Red Black Tree)
*
* @author skywang
* @date 2013/11/18
*/
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include "rbtree.h"
#define rb_parent(r) ((r)->parent)
#define rb_color(r) ((r)->color)
#define rb_is_red(r) ((r)->color==RED)
#define rb_is_black(r) ((r)->color==BLACK)
#define rb_set_black(r) do { (r)->color = BLACK; } while (0)
#define rb_set_red(r) do { (r)->color = RED; } while (0)
#define rb_set_parent(r,p) do { (r)->parent = (p); } while (0)
#define rb_set_color(r,c) do { (r)->color = (c); } while (0)
/*
* "红黑树的根"
*/
RBRoot* create_rbtree()
{
RBRoot *root = (RBRoot *)malloc(sizeof(RBRoot));
root->node = NULL;
return root;
}
/*
* "红黑树"
*/
int ListTraverse(LinkList L)
{
LinkList p = L->next;
while (p)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
return 1;
}
static void inorder(RBTree tree)
{
if (tree != NULL)
{
inorder(tree->left);
printf("%s:", tree->key.filename);
ListTraverse(tree->key.index);
inorder(tree->right);
}
}
void inorder_rbtree(RBRoot *root)
{
if (root)
inorder(root->node);
}
/*
* ()"红黑树x"key
*/
static Node* search(RBTree x, int key)
{
if (x == NULL || x->key.hashfile == key)
return x;
if (key < x->key.hashfile)
return search(x->left, key);
else
return search(x->right, key);
}
RBleaf* rbtree_search(RBRoot *root, int key)
{
if (root) {
Node* temp = search(root->node, key);
if ( temp!= NULL)
{
return &temp->key;
}
}
return NULL;
}
/*
* (x)"红黑树中数据值大于该结点""最小结点"
*/
static Node* rbtree_successor(RBTree x)
{
// 如果x存在右孩子则"x的后继结点"为 "以其右孩子为根的子树的最小结点"。
if (x->right != NULL)
return minimum(x->right);
// 如果x没有右孩子。则x有以下两种可能
// (01) x是"一个左孩子",则"x的后继结点"为 "它的父结点"。
// (02) x是"一个右孩子",则查找"x的最低的父结点并且该父结点要具有左孩子",找到的这个"最低的父结点"就是"x的后继结点"。
Node* y = x->parent;
while ((y != NULL) && (x == y->right))
{
x = y;
y = y->parent;
}
return y;
}
/*
* (x)"红黑树中数据值小于该结点""最大结点"
*/
static Node* rbtree_predecessor(RBTree x)
{
// 如果x存在左孩子则"x的前驱结点"为 "以其左孩子为根的子树的最大结点"。
if (x->left != NULL)
return maximum(x->left);
// 如果x没有左孩子。则x有以下两种可能
// (01) x是"一个右孩子",则"x的前驱结点"为 "它的父结点"。
// (01) x是"一个左孩子",则查找"x的最低的父结点并且该父结点要具有右孩子",找到的这个"最低的父结点"就是"x的前驱结点"。
Node* y = x->parent;
while ((y != NULL) && (x == y->left))
{
x = y;
y = y->parent;
}
return y;
}
/*
* (x)
*
* (x)
* px px
* / /
* x y
* / \ --()--> / \ #
* lx y x ry
* / \ / \
* ly ry lx ly
*
*
*/
static void rbtree_left_rotate(RBRoot *root, Node *x)
{
// 设置x的右孩子为y
Node *y = x->right;
// 将 “y的左孩子” 设为 “x的右孩子”
// 如果y的左孩子非空将 “x” 设为 “y的左孩子的父亲”
x->right = y->left;
if (y->left != NULL)
y->left->parent = x;
// 将 “x的父亲” 设为 “y的父亲”
y->parent = x->parent;
if (x->parent == NULL)
{
//tree = y; // 如果 “x的父亲” 是空节点则将y设为根节点
root->node = y; // 如果 “x的父亲” 是空节点则将y设为根节点
}
else
{
if (x->parent->left == x)
x->parent->left = y; // 如果 x是它父节点的左孩子则将y设为“x的父节点的左孩子”
else
x->parent->right = y; // 如果 x是它父节点的左孩子则将y设为“x的父节点的左孩子”
}
// 将 “x” 设为 “y的左孩子”
y->left = x;
// 将 “x的父节点” 设为 “y”
x->parent = y;
}
/*
* (y)
*
* (y)
* py py
* / /
* y x
* / \ --()--> / \ #
* x ry lx y
* / \ / \ #
* lx rx rx ry
*
*/
static void rbtree_right_rotate(RBRoot *root, Node *y)
{
// 设置x是当前节点的左孩子。
Node *x = y->left;
// 将 “x的右孩子” 设为 “y的左孩子”
// 如果"x的右孩子"不为空的话,将 “y” 设为 “x的右孩子的父亲”
y->left = x->right;
if (x->right != NULL)
x->right->parent = y;
// 将 “y的父亲” 设为 “x的父亲”
x->parent = y->parent;
if (y->parent == NULL)
{
//tree = x; // 如果 “y的父亲” 是空节点则将x设为根节点
root->node = x; // 如果 “y的父亲” 是空节点则将x设为根节点
}
else
{
if (y == y->parent->right)
y->parent->right = x; // 如果 y是它父节点的右孩子则将x设为“y的父节点的右孩子”
else
y->parent->left = x; // (y是它父节点的左孩子) 将x设为“x的父节点的左孩子”
}
// 将 “y” 设为 “x的右孩子”
x->right = y;
// 将 “y的父节点” 设为 “x”
y->parent = x;
}
/*
*
*
* ()
*
*
*
* root
* node // 对应《算法导论》中的z
*/
static void rbtree_insert_fixup(RBRoot *root, Node *node)
{
Node *parent, *gparent;
// 若“父节点存在,并且父节点的颜色是红色”
while ((parent = rb_parent(node)) && rb_is_red(parent))
{
gparent = rb_parent(parent);
//若“父节点”是“祖父节点的左孩子”
if (parent == gparent->left)
{
// Case 1条件叔叔节点是红色
{
Node *uncle = gparent->right;
if (uncle && rb_is_red(uncle))
{
rb_set_black(uncle);
rb_set_black(parent);
rb_set_red(gparent);
node = gparent;
continue;
}
}
// Case 2条件叔叔是黑色且当前节点是右孩子
if (parent->right == node)
{
Node *tmp;
rbtree_left_rotate(root, parent);
tmp = parent;
parent = node;
node = tmp;
}
// Case 3条件叔叔是黑色且当前节点是左孩子。
rb_set_black(parent);
rb_set_red(gparent);
rbtree_right_rotate(root, gparent);
}
else//若“z的父节点”是“z的祖父节点的右孩子”
{
// Case 1条件叔叔节点是红色
{
Node *uncle = gparent->left;
if (uncle && rb_is_red(uncle))
{
rb_set_black(uncle);
rb_set_black(parent);
rb_set_red(gparent);
node = gparent;
continue;
}
}
// Case 2条件叔叔是黑色且当前节点是左孩子
if (parent->left == node)
{
Node *tmp;
rbtree_right_rotate(root, parent);
tmp = parent;
parent = node;
node = tmp;
}
// Case 3条件叔叔是黑色且当前节点是右孩子。
rb_set_black(parent);
rb_set_red(gparent);
rbtree_left_rotate(root, gparent);
}
}
// 将根节点设为黑色
rb_set_black(root->node);
}
/*
* (node)
*
*
* root
* node // 对应《算法导论》中的z
*/
static void rbtree_insert(RBRoot *root, Node *node)
{
Node *y = NULL;
Node *x = root->node;
// 1. 将红黑树当作一颗二叉查找树,将节点添加到二叉查找树中。
while (x != NULL)
{
y = x;
if (node->key.hashfile < x->key.hashfile)
x = x->left;
else
x = x->right;
}
rb_parent(node) = y;
if (y != NULL)
{
if (node->key.hashfile < y->key.hashfile)
y->left = node; // 情况2若“node所包含的值” < “y所包含的值”则将node设为“y的左孩子”
else
y->right = node; // 情况3(“node所包含的值” >= “y所包含的值”)将node设为“y的右孩子”
}
else
{
root->node = node; // 情况1若y是空节点则将node设为根
}
// 2. 设置节点的颜色为红色
node->color = RED;
// 3. 将它重新修正为一颗二叉查找树
rbtree_insert_fixup(root, node);
}
/*
*
*
*
* key
* parent
* left
* right
*/
static Node* create_rbtree_node(RBleaf key, Node *parent, Node *left, Node* right)
{
Node* p;
if ((p = (Node *)malloc(sizeof(Node))) == NULL)
return NULL;
p->key = key;
p->left = left;
p->right = right;
p->parent = parent;
p->color = BLACK; // 默认为黑色
return p;
}
/*
* (key)
*
*
* root
* key
*
* 0
* -1
*/
int insert_rbtree(RBRoot *root, RBleaf key)
{
Node *node; // 新建结点
// 不允许插入相同键值的节点。
// (若想允许插入相同键值的节点,注释掉下面两句话即可!)
if (search(root->node, key.hashfile) != NULL)
return -1;
// 如果新建结点失败,则返回。
if ((node = create_rbtree_node(key, NULL, NULL, NULL)) == NULL)
return -1;
rbtree_insert(root, node);
return 0;
}
/*
*
*
* ()
*
*
*
* root
* node
*/
static void rbtree_delete_fixup(RBRoot *root, Node *node, Node *parent)
{
Node *other;
while ((!node || rb_is_black(node)) && node != root->node)
{
if (parent->left == node)
{
other = parent->right;
if (rb_is_red(other))
{
// Case 1: x的兄弟w是红色的
rb_set_black(other);
rb_set_red(parent);
rbtree_left_rotate(root, parent);
other = parent->right;
}
if ((!other->left || rb_is_black(other->left)) &&
(!other->right || rb_is_black(other->right)))
{
// Case 2: x的兄弟w是黑色且w的俩个孩子也都是黑色的
rb_set_red(other);
node = parent;
parent = rb_parent(node);
}
else
{
if (!other->right || rb_is_black(other->right))
{
// Case 3: x的兄弟w是黑色的并且w的左孩子是红色右孩子为黑色。
rb_set_black(other->left);
rb_set_red(other);
rbtree_right_rotate(root, other);
other = parent->right;
}
// Case 4: x的兄弟w是黑色的并且w的右孩子是红色的左孩子任意颜色。
rb_set_color(other, rb_color(parent));
rb_set_black(parent);
rb_set_black(other->right);
rbtree_left_rotate(root, parent);
node = root->node;
break;
}
}
else
{
other = parent->left;
if (rb_is_red(other))
{
// Case 1: x的兄弟w是红色的
rb_set_black(other);
rb_set_red(parent);
rbtree_right_rotate(root, parent);
other = parent->left;
}
if ((!other->left || rb_is_black(other->left)) &&
(!other->right || rb_is_black(other->right)))
{
// Case 2: x的兄弟w是黑色且w的俩个孩子也都是黑色的
rb_set_red(other);
node = parent;
parent = rb_parent(node);
}
else
{
if (!other->left || rb_is_black(other->left))
{
// Case 3: x的兄弟w是黑色的并且w的左孩子是红色右孩子为黑色。
rb_set_black(other->right);
rb_set_red(other);
rbtree_left_rotate(root, other);
other = parent->left;
}
// Case 4: x的兄弟w是黑色的并且w的右孩子是红色的左孩子任意颜色。
rb_set_color(other, rb_color(parent));
rb_set_black(parent);
rb_set_black(other->left);
rbtree_right_rotate(root, parent);
node = root->node;
break;
}
}
}
if (node)
rb_set_black(node);
}
/*
*
*
*
* tree
* node
*/
void rbtree_delete(RBRoot *root, Node *node)
{
Node *child, *parent;
int color;
// 被删除节点的"左右孩子都不为空"的情况。
if ((node->left != NULL) && (node->right != NULL))
{
// 被删节点的后继节点。(称为"取代节点")
// 用它来取代"被删节点"的位置,然后再将"被删节点"去掉。
Node *replace = node;
// 获取后继节点
replace = replace->right;
while (replace->left != NULL)
replace = replace->left;
// "node节点"不是根节点(只有根节点不存在父节点)
if (rb_parent(node))
{
if (rb_parent(node)->left == node)
rb_parent(node)->left = replace;
else
rb_parent(node)->right = replace;
}
else
// "node节点"是根节点,更新根节点。
root->node = replace;
// child是"取代节点"的右孩子,也是需要"调整的节点"。
// "取代节点"肯定不存在左孩子!因为它是一个后继节点。
child = replace->right;
parent = rb_parent(replace);
// 保存"取代节点"的颜色
color = rb_color(replace);
// "被删除节点"是"它的后继节点的父节点"
if (parent == node)
{
parent = replace;
}
else
{
// child不为空
if (child)
rb_set_parent(child, parent);
parent->left = child;
replace->right = node->right;
rb_set_parent(node->right, replace);
}
replace->parent = node->parent;
replace->color = node->color;
replace->left = node->left;
node->left->parent = replace;
if (color == BLACK)
rbtree_delete_fixup(root, child, parent);
free(node);
return;
}
if (node->left != NULL)
child = node->left;
else
child = node->right;
parent = node->parent;
// 保存"取代节点"的颜色
color = node->color;
if (child)
child->parent = parent;
// "node节点"不是根节点
if (parent)
{
if (parent->left == node)
parent->left = child;
else
parent->right = child;
}
else
root->node = child;
if (color == BLACK)
rbtree_delete_fixup(root, child, parent);
free(node);
}
/*
* key
*
*
* tree
* key
*/
void delete_rbtree(RBRoot *root, RBleaf key)
{
Node *z, *node;
if ((z = search(root->node, key.hashfile)) != NULL)
rbtree_delete(root, z);
}
/*
*
*/
static void rbtree_destroy(RBTree tree)
{
if (tree == NULL)
return;
if (tree->left != NULL)
rbtree_destroy(tree->left);
if (tree->right != NULL)
rbtree_destroy(tree->right);
free(tree);
}
void destroy_rbtree(RBRoot *root)
{
if (root != NULL)
rbtree_destroy(root->node);
free(root);
}
/*
* "红黑树"
*
* tree --
* key --
* direction -- 0;
* -1;
* 1
*/
static void rbtree_print(RBTree tree, RBleaf key, int direction)
{
if (tree != NULL)
{
if (direction == 0) // tree是根节点
printf("%2d(B) is root\n", tree->key);
else // tree是分支节点
printf("%2d(%s) is %2d's %6s child\n", tree->key, rb_is_red(tree) ? "R" : "B", key, direction == 1 ? "right" : "left");
rbtree_print(tree->left, tree->key, -1);
rbtree_print(tree->right, tree->key, 1);
}
}
void print_rbtree(RBRoot *root)
{
if (root != NULL && root->node != NULL)
rbtree_print(root->node, root->node->key, 0);
}

@ -0,0 +1,44 @@
#pragma once
#define RED 0 // 红色节点
#define BLACK 1 // 黑色节点
#include "List.h"
typedef struct RBleaf {
int hashfile;
char filename[50];
LinkList index;
}RBleaf;
// 红黑树的节点
typedef struct RBTreeNode {
unsigned char color; // 颜色(RED 或 BLACK)
RBleaf key; // 关键字(键值)
struct RBTreeNode *left; // 左孩子
struct RBTreeNode *right; // 右孩子
struct RBTreeNode *parent; // 父结点
}Node, *RBTree;
// 红黑树的根
typedef struct rb_root {
Node *node;
}RBRoot;
// 创建红黑树,返回"红黑树的根"
RBRoot* create_rbtree();
// 销毁红黑树
void destroy_rbtree(RBRoot *root);
// 将结点插入到红黑树中。插入成功返回0失败返回-1。
int insert_rbtree(RBRoot *root, RBleaf key);
// 删除结点(key为节点的值)
void delete_rbtree(RBRoot *root, RBleaf key);
// 中序遍历"红黑树"
void inorder_rbtree(RBRoot *root);
// (递归实现)查找"红黑树"中键值为key的节点。找到的话返回0否则返回-1。
RBleaf* rbtree_search(RBRoot *root, int hashkey);
// 打印红黑树
void print_rbtree(RBRoot *root);
Loading…
Cancel
Save