杂乱的数据池子,我们从中选出第几个数据是谁?或者给你个key,找出排名第几?
比如班级一次考试,给你分数,查看排名?或者给你排名查看data?
我们利用红黑树,增加size字段。
所谓size就是当前节点包含节点的个数,包括自己。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef enum enColor
{
RED,
BLACK
}Color;
typedef struct stNode
{
int data;
Color color;
int size;
struct stNode* pP;
struct stNode* pL;
struct stNode* pR;
}Node;
void print_node(Node* pNode)
{
printf("D%d:C%d:S%d\t",pNode->data,pNode->color,pNode->size);
}
Node g_nil = { 0,BLACK,0,NULL,NULL,NULL };
Node* pNil = &g_nil;
void print_inorder(Node* pTree)
{
if (pTree != pNil)
{
print_inorder(pTree->pL);
print_node(pTree);
print_inorder(pTree->pR);
}
}
void print_preorder(Node* pTree)
{
if (pTree != pNil)
{
print_node(pTree);
print_preorder(pTree->pL);
print_preorder(pTree->pR);
}
}
void print_tree(Node* pTree)
{
printf("inorder \n");
print_inorder(pTree);
printf("\n");
printf("preorder \n");
print_preorder(pTree);
printf("\n");
}
void left_rotate(Node** ppTree, Node* pOper)
{
Node* pRSon = pOper->pR;
if (pRSon == pNil)
{
print_node(pOper);
printf("error happened, no need left rotate \n");
return;
}
pOper->pR = pRSon->pL;
if (pRSon->pL != pNil)
pRSon->pL->pP = pOper;
pRSon->pP = pOper->pP;
if (pOper->pP == pNil)
{
*ppTree = pRSon;
}
else if (pOper->pP->pL == pOper)
{
pOper->pP->pL = pRSon;
}
else
{
pOper->pP->pR = pRSon;
}
pRSon->pL = pOper;
pOper->pP = pRSon;
pRSon->size = pOper->size;
pOper->size = pOper->pL->size + pOper->pR->size + 1;
}
void right_rotate(Node** ppTree, Node* pOper)
{
Node* pLSon = pOper->pL;
if (pLSon == pNil)
{
print_node(pOper);
printf("error happened, no need right rotate \n");
return;
}
pOper->pL = pLSon->pR;
if (pLSon->pR != pNil)
pLSon->pR->pP = pOper;
pLSon->pP = pOper->pP;
if (pOper->pP == pNil)
{
*ppTree = pLSon;
}
else if (pOper->pP->pL == pOper)
{
pOper->pP->pL = pLSon;
}
else
{
pOper->pP->pR = pLSon;
}
pLSon->pR = pOper;
pOper->pP = pLSon;
pLSon->size = pOper->size;
pOper->size = pOper->pL->size + pOper->pR->size + 1;
}
void insert_fixup_parent_is_leftson_of_grandpa(Node** ppTree, Node** ppNode, Node** ppParent)
{
Node* pNode = *ppNode;
Node* pParent = *ppParent;
Node* pGrandpa = pParent->pP;
Node* pUncle = pGrandpa->pR;
if (pUncle != pNil && pUncle->color == RED)
{
pParent->color = BLACK;
pUncle->color = BLACK;
pGrandpa->color = RED;
*ppNode = pGrandpa;
*ppParent = pGrandpa->pP;
}
else if (pParent->pR == pNode)
{
left_rotate(ppTree, pParent);
*ppNode = pParent;
*ppParent = pParent->pP;
}
else
{
pParent->color = BLACK;
pGrandpa->color = RED;
right_rotate(ppTree, pGrandpa);
}
}
void insert_fixup_parent_is_rightson_of_grandpa(Node** ppTree, Node** ppNode, Node** ppParent)
{
Node* pNode = *ppNode;
Node* pParent = *ppParent;
Node* pGrandpa = pParent->pP;
Node* pUncle = pGrandpa->pL;
if (pUncle != pNil && pUncle->color == RED)
{
pParent->color = BLACK;
pUncle->color = BLACK;
pGrandpa->color = RED;
*ppNode = pGrandpa;
*ppParent = pGrandpa->pP;
}
else if (pParent->pL == pNode)
{
right_rotate(ppTree, pParent);
*ppNode = pParent;
*ppParent = pParent->pP;
}
else
{
pParent->color = BLACK;
pGrandpa->color = RED;
left_rotate(ppTree, pGrandpa);
}
}
void insert_fixup(Node** ppTree, Node* pNode)
{
Node* pParent = pNode->pP;
while (pParent != pNil && pParent->color == RED &&
pNode != pNil && pNode->color == RED)
{
if (pParent->pP == pNil)
{
print_node(pNode);
print_node(pParent);
printf("insert fixup no need, cause grandpa is nil \n");
return;
}
if (pParent->pP->pL == pParent)
{
insert_fixup_parent_is_leftson_of_grandpa(ppTree,&pNode,&pParent);
}
else
{
insert_fixup_parent_is_rightson_of_grandpa(ppTree, &pNode, &pParent);
}
}
(*ppTree)->color = BLACK;
}
void insert(Node** ppTree, Node* pNode)
{
Node* pTree = *ppTree;
Node* pParent = pNil;
while (pTree != pNil)
{
pParent = pTree;
pTree->size += 1;
if (pNode->data < pTree->data)
pTree = pTree->pL;
else
pTree = pTree->pR;
}
pNode->pP = pParent;
if (pParent == pNil)
*ppTree = pNode;
else if (pNode->data < pParent->data)
pParent->pL = pNode;
else
pParent->pR = pNode;
insert_fixup(ppTree,pNode);
}
Node* new_node(int data)
{
Node* pNewNode = (Node*)malloc(sizeof(Node));
pNewNode->data = data;
pNewNode->color = RED;
pNewNode->size = 1;
pNewNode->pL = pNil;
pNewNode->pR = pNil;
pNewNode->pP = pNil;
return pNewNode;
}
int os_select(Node** ppTree, int index)
{
Node* pTree = *ppTree;
int curRootIndex = pTree->pL->size + 1;
if (curRootIndex == index)
{
print_node(pTree);
return pTree->data;
}
else if (index < curRootIndex)
{
os_select(&pTree->pL,index);
}
else
{
os_select(&pTree->pR,index - curRootIndex);
}
}
Node* find(Node** ppTree, int data)
{
Node* pTree = *ppTree;
while (pTree != pNil)
{
if (pTree->data == data)
return pTree;
else if (data < pTree->data)
pTree = pTree->pL;
else
pTree = pTree->pR;
}
return pNil;
}
int os_index(Node** ppTree, int data)
{
Node* pNode = find(ppTree, data);
if (pNode == pNil)
{
printf("no %d node in tree, os_index fail \n", data);
return 0;
}
int curIndex = pNode->pL->size + 1;
Node* pTree = *ppTree;
while (pNode != pTree)
{
if (pNode->pP->pR == pNode)
{
curIndex = pNode->pP->pL->size + 1 + curIndex;
}
pNode = pNode->pP;
}
printf("$$$$$$$$data: %d is %dth in tree \n", data,curIndex);
return curIndex;
}
void test_insert()
{
int arr[] = { 5,3,2,1,4,9,6,10,12 };
Node* pNode;
Node* pTree = pNil;
int i;
for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
pNode = new_node(arr[i]);
insert(&pTree,pNode);
printf("after insert arr[%d]=%d \n",i,arr[i]);
print_tree(pTree);
}
printf("#####the 7th data is ######\n");
os_select(&pTree,7);
printf("\n");
os_index(&pTree,9);
}
int main()
{
test_insert();
return 0;
}