顺序搜索树

杂乱的数据池子,我们从中选出第几个数据是谁?或者给你个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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值