数据结构总结一

数据结构中基本结构的总结:

包括:链表,栈, 队列,BST(二叉搜索树)以及RBT源码(和一篇博文介绍)

链表的实现:

首先链表就是最基本的数据结构了,由于太过基础就不再多说。

#include
#include

typedef struct list
{
	int nValue;
	struct list *pNext;
}List;

List *CreateList()//链表创建
{
	List *pHead = NULL;
	List *pTail = NULL;

	List *pTemp = NULL;

	int nNum;
	int nCount;
	printf("请输入结点个数:\n");
	scanf("%d",&nCount);

	while(nCount)
	{
		printf("请输入节点的值:\n");
		scanf("%d",&nNum);

		pTemp = (List*)malloc(sizeof(List));
		pTemp->nValue = nNum;
		pTemp->pNext = NULL;

		//节点添加
		if(pHead == NULL)
		{
			pHead = pTemp;
		}
		else
		{
			pTail->pNext = pTemp;
		}
		pTail = pTemp;

		nCount--;
	}

	return pHead;
}

void Print(List *pHead)//链表打印
{
	if(pHead == NULL)return;

	while(pHead)
	{
		printf("%d ",pHead->nValue);
		pHead = pHead->pNext;
	}
}

void RePrint(List *pHead)//链表逆序打印
{
	if(pHead == NULL)return;

	//下一个
	RePrint(pHead->pNext);

	//打印
	printf("%d ",pHead->nValue);
}

List* Reverse(List *pHead)//链表翻转
{
	if(pHead == NULL || pHead->pNext == NULL)return pHead;

	List *p1 = NULL;
	List *p2 = pHead;
	List *p3 = pHead->pNext;

	while(p3 != NULL)
	{
		p2->pNext = p1;

		p1 = p2;
		p2 = p3;
		p3 = p3->pNext;
	}

	p2->pNext = p1;
	return p2;
}

int main()
{
	List *pHead = NULL;
	pHead = CreateList();
	Print(pHead);
	printf("\n");
	RePrint(pHead);
	printf("\n");
	pHead = Reverse(pHead);
	Print(pHead);
	printf("\n");
	return 0;
}

代码都比较基础,但是值得一提的是就是链表的反转实现。原理就是利用三个指针分别指向NULL,head,head->next;然后先是将p2指针指向p1,就可以实现每个节点的链表指向前一个节点。再然后逐个遍历,就将链表进行了倒排。
至于逆序打印就是利用递归先是遍历下个节点,然后再打印数据。

队列的实现:

队列用c语言实现也是利用链表的思想,只是再将链表的头尾指针封装一下,封装到队列这个结构体。以后的操作都是利用该结构体进行传参,将头尾指针进行传参,来实现对列的基本功能。

#include
#include

typedef struct node
{
	int nValue;
	struct node *pNext;
}MyQueue;

typedef struct queue
{
	int nCount;
	MyQueue *pHead;
	MyQueue *pTail;
}Queue;

void q_Init(Queue **pQueue)
{
	*pQueue = (Queue*)malloc(sizeof(Queue));
	(*pQueue)->nCount = 0;
	(*pQueue)->pHead = NULL;
	(*pQueue)->pTail = NULL;
}

void q_Push(Queue *pQueue,int nNum)
{
	if(pQueue == NULL)return;

	MyQueue *pTemp = NULL;
	pTemp = (MyQueue*)malloc(sizeof(MyQueue));
	pTemp->nValue = nNum;
	pTemp->pNext = NULL;

	//尾添加
	if(pQueue->pHead == NULL)
	{
		pQueue->pHead = pTemp;
	}
	else
	{
		pQueue->pTail->pNext = pTemp;
	}
	pQueue->pTail = pTemp;
	pQueue->nCount++;
}

int q_Pop(Queue *pQueue)
{
	if(pQueue == NULL)exit(1);

	if(pQueue->nCount == 0)return -1;

	MyQueue *pDel = pQueue->pHead;
	int nNum = pDel->nValue;

	pQueue->pHead = pQueue->pHead->pNext;
	
	free(pDel);
	pDel = NULL;
	pQueue->nCount--;
	if(pQueue->nCount == 0)
	{
		pQueue->pTail = NULL;
	}

	return nNum;
}

int q_IsEmpty(Queue *pQueue)
{
	if(pQueue == NULL)exit(1);

	return pQueue->nCount == 0?1:0;
}


int main()
{
	Queue *pQueue = NULL;
	q_Init(&pQueue);
	q_Push(pQueue,1);
	q_Push(pQueue,2);
	q_Push(pQueue,3);
	q_Push(pQueue,4);

	printf("%d\n",q_Pop(pQueue));
	printf("%d\n",q_Pop(pQueue));
	printf("%d\n",q_Pop(pQueue));
	printf("%d\n",q_Pop(pQueue));
	return 0;
}

就如上面提到的一样核心就是利用链表知识,将数据进行封装,首先封装为一个类似链表的节点,一个data数据和一个next指针。其次就是将用来调整链表的头尾指针封装为另外一个结构体。

栈:

栈的实现思想和队列很相似,但是区别就是栈使用一个指针进行维护,但如何才能利用一个指针进行维护一个链表呢。这里就需要用到头插法,而队列就是利用尾插法。这就是二者的区别所在。

#include
#include

typedef struct node
{
	int nValue;
	struct node *pNext;
}MyStack;

typedef struct stack
{
	MyStack *pTop;
	int nCount;
}Stack;

void s_Init(Stack **pStack)
{
	*pStack = (Stack*)malloc(sizeof(Stack));
	(*pStack)->nCount = 0;
	(*pStack)->pTop = NULL;
}

void s_Push(Stack *pStack,int nNum)
{
	if(pStack == NULL)
	{
		printf("栈不存在!\n");
		exit(1);
	}

	MyStack *pTemp = NULL;
	pTemp = (MyStack*)malloc(sizeof(MyStack));
	pTemp->nValue = nNum;
	pTemp->pNext = pStack->pTop;
	pStack->pTop = pTemp;
	pStack->nCount++;
}

int s_Pop(Stack *pStack)
{
	if(pStack == NULL)exit(1);

	if(pStack->pTop == NULL)return -1;

	MyStack *pDel = pStack->pTop;
	int nNum = pDel->nValue;

	pStack->pTop = pStack->pTop->pNext;
	free(pDel);
	pDel = NULL;
	
	pStack->nCount--;
	return nNum;
}

void s_Clear(Stack *pStack)
{
	if(pStack == NULL)exit(1);

	while(pStack->nCount != 0)
	{
		s_Pop(pStack);
	}
}

void s_Destroy(Stack **pStack)
{
	if(*pStack == NULL)return;

	s_Clear(*pStack);

	free(*pStack);
	*pStack = NULL;
}

MyStack *s_GetTop(Stack *pStack)
{
	if(pStack == NULL)exit(1);

	return pStack->pTop;
}

int s_GetCount(Stack *pStack)
{
	if(pStack == NULL)exit(1);

	return pStack->nCount;
}

int s_IsEmpty(Stack *pStack)
{
	if(pStack == NULL)exit(1);

	return pStack->nCount == 0 ? 1 : 0 ;
}

int main()
{
	Stack *pStack = NULL;
	s_Init(&pStack);
	s_Push(pStack,1);
	s_Push(pStack,2);
	s_Push(pStack,3);
	s_Push(pStack,4);

	printf("%d\n",s_Pop(pStack));
	printf("%d\n",s_Pop(pStack));
	printf("%d\n",s_Pop(pStack));
	printf("%d\n",s_Pop(pStack));

	s_Destroy(&pStack);
	s_Push(pStack,1);
	return 0;
}

值得一提的是就是应该注意一下头插法和尾插法区别所在(对比栈和队列的push函数)。

利用栈模拟队列:

使用栈模拟队列就是利用两个栈循环进行push和pop操作,从而实现队列的功能。
比如:首先使用stack1将数据进行push,当要对队列进行输出时,就将stack1挨个pop并将数据push到stack2里面。最后将stack2的栈顶数据pop掉即可。(然后循环此操作就可实现pop任务)这就是实现队列模拟的核心。

#include
#include

typedef struct node
{
	int nValue;
	struct node *pNext;
}MyStack;

typedef struct stack
{
	MyStack *pTop;
	int nCount;
}Stack;

typedef struct queue
{
	int nCount;
	Stack *pStack1;
	Stack *pStack2;
}Queue;

void s_Init(Stack **pStack)
{
	*pStack = (Stack*)malloc(sizeof(Stack));
	(*pStack)->nCount = 0;
	(*pStack)->pTop = NULL;
}

void s_Push(Stack *pStack,int nNum)
{
	if(pStack == NULL)
	{
		printf("栈不存在!\n");
		exit(1);
	}

	MyStack *pTemp = NULL;
	pTemp = (MyStack*)malloc(sizeof(MyStack));
	pTemp->nValue = nNum;
	pTemp->pNext = pStack->pTop;
	pStack->pTop = pTemp;
	pStack->nCount++;
}

int s_Pop(Stack *pStack)
{
	if(pStack == NULL)exit(1);

	if(pStack->pTop == NULL)return -1;

	MyStack *pDel = pStack->pTop;
	int nNum = pDel->nValue;

	pStack->pTop = pStack->pTop->pNext;
	free(pDel);
	pDel = NULL;
	
	pStack->nCount--;
	return nNum;
}

void s_Clear(Stack *pStack)
{
	if(pStack == NULL)exit(1);

	while(pStack->nCount != 0)
	{
		s_Pop(pStack);
	}
}

void s_Destroy(Stack **pStack)
{
	if(*pStack == NULL)return;

	s_Clear(*pStack);

	free(*pStack);
	*pStack = NULL;
}

MyStack *s_GetTop(Stack *pStack)
{
	if(pStack == NULL)exit(1);

	return pStack->pTop;
}

int s_GetCount(Stack *pStack)
{
	if(pStack == NULL)exit(1);

	return pStack->nCount;
}

int s_IsEmpty(Stack *pStack)
{
	if(pStack == NULL)exit(1);

	return pStack->nCount == 0 ? 1 : 0 ;
}

void q_Init(Queue **pQueue)
{
	*pQueue = (Queue*)malloc(sizeof(Queue));
	(*pQueue)->nCount = 0;
	s_Init(&((*pQueue)->pStack1));
	s_Init(&((*pQueue)->pStack2));
}

void q_Push(Queue *pQueue,int nNum)
{
	if(pQueue == NULL)exit(1);

	//栈1入队
	//栈2若有元素,将其放入栈1内,再向栈1压入
	while(!s_IsEmpty(pQueue->pStack2))
	{
		s_Push(pQueue->pStack1,s_Pop(pQueue->pStack2));
	}

	s_Push(pQueue->pStack1,nNum);
	pQueue->nCount++;
}

int q_Pop(Queue *pQueue)
{
	if(pQueue == NULL)exit(1);

	if(pQueue->nCount == 0)return -1;

	//栈2弹出
	//栈1非空 栈1元素入栈2  栈2弹出
	while(!s_IsEmpty(pQueue->pStack1))
	{
		s_Push(pQueue->pStack2,s_Pop(pQueue->pStack1));
	}

	int nNum;
	nNum = s_Pop(pQueue->pStack2);
	pQueue->nCount--;
	return nNum;
}

int main()
{
	Queue *pQueue = NULL;
	q_Init(&pQueue);
	q_Push(pQueue,1);
	q_Push(pQueue,2);
	q_Push(pQueue,3);
	q_Push(pQueue,4);

	printf("%d\n",q_Pop(pQueue));
	printf("%d\n",q_Pop(pQueue));
	printf("%d\n",q_Pop(pQueue));
	printf("%d\n",q_Pop(pQueue));
	return 0;
}

值得注意的是,将数据进行入队的时候必须得进入有数据的栈中(非空栈),方便以后的操作。

队列模拟栈:

这和栈模拟队列思想相近,也是利用两个队列指针来模拟栈。比如:
当数据进行push时就将数据放入到非空的队列中。当进行栈的pop操作时就将非空队列中除了后一个元素放入到空的队列中。然后将最后一个元素进行队列的pop操作。即可

#include
#include

typedef struct node
{
	int nValue;
	struct node *pNext;
}MyQueue;

typedef struct queue
{
	int nCount;
	MyQueue *pHead;
	MyQueue *pTail;
}Queue;

typedef struct stack
{
	int nCount;
	Queue *pQueue1;
	Queue *pQueue2;
}Stack;

void q_Init(Queue **pQueue)
{
	*pQueue = (Queue*)malloc(sizeof(Queue));
	(*pQueue)->nCount = 0;
	(*pQueue)->pHead = NULL;
	(*pQueue)->pTail = NULL;
}

void q_Push(Queue *pQueue,int nNum)
{
	if(pQueue == NULL)return;

	MyQueue *pTemp = NULL;
	pTemp = (MyQueue*)malloc(sizeof(MyQueue));
	pTemp->nValue = nNum;
	pTemp->pNext = NULL;

	//尾添加
	if(pQueue->pHead == NULL)
	{
		pQueue->pHead = pTemp;
	}
	else
	{
		pQueue->pTail->pNext = pTemp;
	}
	pQueue->pTail = pTemp;
	pQueue->nCount++;
}

int q_Pop(Queue *pQueue)
{
	if(pQueue == NULL)exit(1);

	if(pQueue->nCount == 0)return -1;

	MyQueue *pDel = pQueue->pHead;
	int nNum = pDel->nValue;

	pQueue->pHead = pQueue->pHead->pNext;
	
	free(pDel);
	pDel = NULL;
	pQueue->nCount--;
	if(pQueue->nCount == 0)
	{
		pQueue->pTail = NULL;
	}

	return nNum;
}

int q_IsEmpty(Queue *pQueue)
{
	if(pQueue == NULL)exit(1);

	return pQueue->nCount == 0?1:0;
}

void s_Init(Stack **pStack)
{
	*pStack = (Stack*)malloc(sizeof(Stack));
	(*pStack)->nCount = 0;
	q_Init(&((*pStack)->pQueue1));
	q_Init(&((*pStack)->pQueue2));
}

void s_Push(Stack *pStack,int nNum)
{
	if(pStack == NULL)exit(1);

	if(!q_IsEmpty(pStack->pQueue1))
	{
		q_Push(pStack->pQueue1,nNum);
	}
	else
	{
		q_Push(pStack->pQueue2,nNum);
	}
	pStack->nCount++;
}

int s_Pop(Stack *pStack)
{
	if(pStack == NULL)exit(1);

	if(pStack->nCount == 0)return -1;

	int nNum;

	//将非空队列除尾元素以外全都压入空对列
	if(!q_IsEmpty(pStack->pQueue1))
	{
		while(pStack->pQueue1->nCount > 1)
		{
			q_Push(pStack->pQueue2,q_Pop(pStack->pQueue1));
		}
		nNum = q_Pop(pStack->pQueue1);
	}
	else
	{
		while(pStack->pQueue2->nCount > 1)
		{
			q_Push(pStack->pQueue1,q_Pop(pStack->pQueue2));
		}
		nNum = q_Pop(pStack->pQueue2);
	}

	pStack->nCount--;
	return nNum;
}

int main()
{
	Stack *pStack = NULL;
	s_Init(&pStack);
	s_Push(pStack,1);
	s_Push(pStack,2);
	s_Push(pStack,3);
	s_Push(pStack,4);

	printf("%d\n",s_Pop(pStack));
	printf("%d\n",s_Pop(pStack));
	printf("%d\n",s_Pop(pStack));
	printf("%d\n",s_Pop(pStack));
	return 0;
}

BST(二叉搜索树)

所谓BST就是建造一个数满足任意一个父节点的左儿子小于父节点右儿子大于父节点。这就可以实现当数据进行查找时满足数据的二分查找。时间复杂度降低。但是由于BST本身的性质所以不允许有相同的的数据出现。

#include
#include

typedef struct bst
{
	int nValue;
	struct bst *pLeft;
	struct bst *pRight;
}BST;

void AddNode(BST **pTree,int nNum)
{
	//申请空间
	BST *pTemp = NULL;
	pTemp = (BST*)malloc(sizeof(BST));
	pTemp->nValue = nNum;
	pTemp->pLeft = NULL;
	pTemp->pRight = NULL;

	//空树
	if(*pTree == NULL)
	{
		*pTree = pTemp;
		return;
	}

	//比较
	BST *pNode = *pTree;
	while(pNode)
	{
		if(pNode->nValue > nNum)
		{
			//左侧
			if(pNode->pLeft == NULL)
			{
				pNode->pLeft = pTemp;
				return;
			}
			pNode = pNode->pLeft;
		}
		else if(pNode->nValue < nNum)
		{
			//右侧
			if(pNode->pRight == NULL)
			{
				pNode->pRight = pTemp;
				return;
			}
			pNode = pNode->pRight;
		}
		else
		{
			//报错
			printf("data error.\n");
			free(pTemp);
			pTemp = NULL;
			return;
		}
	}
}

BST *CreateBST(int arr[],int nLength)
{
	if(arr == NULL || nLength <= 0)return NULL;

	int i;
	BST *pRoot = NULL;
	for(i = 0;ipLeft);
	printf("%d ",pTree->nValue);
	Traversal(pTree->pRight);
}

int main()
{
	int arr[] = {10,7,199,3,27,1,6,25,4};
	BST *pTree = CreateBST(arr,sizeof(arr)/sizeof(arr[0]));
	Traversal(pTree);
	printf("\n");
	return 0;
}

这就是基本的建树过程以及中序遍历,值得注意的就是进行插入节点的时候判断一下数据大小即可。

BST转化为List

就是利用中序遍历的顺序,递归将数据存放到双向list中。

#include
#include

typedef struct bst
{
	int nValue;
	struct bst *pLeft;
	struct bst *pRight;
}BST;

void AddNode(BST **pTree,int nNum)
{
	//申请空间
	BST *pTemp = NULL;
	pTemp = (BST*)malloc(sizeof(BST));
	pTemp->nValue = nNum;
	pTemp->pLeft = NULL;
	pTemp->pRight = NULL;

	//空树
	if(*pTree == NULL)
	{
		*pTree = pTemp;
		return;
	}

	//比较
	BST *pNode = *pTree;
	while(pNode)
	{
		if(pNode->nValue > nNum)
		{
			//左侧
			if(pNode->pLeft == NULL)
			{
				pNode->pLeft = pTemp;
				return;
			}
			pNode = pNode->pLeft;
		}
		else if(pNode->nValue < nNum)
		{
			//右侧
			if(pNode->pRight == NULL)
			{
				pNode->pRight = pTemp;
				return;
			}
			pNode = pNode->pRight;
		}
		else
		{
			//报错
			printf("data error.\n");
			free(pTemp);
			pTemp = NULL;
			return;
		}
	}
}

BST *CreateBST(int arr[],int nLength)
{
	if(arr == NULL || nLength <= 0)return NULL;

	int i;
	BST *pRoot = NULL;
	for(i = 0;ipLeft);
	printf("%d ",pTree->nValue);
	Traversal(pTree->pRight);
}

void BSTToList(BST *pTree,BST **pHead,BST **pTail)
{
	if(pTree == NULL)return;

	//左
	BSTToList(pTree->pLeft,pHead,pTail);

	//双向链表节点添加
	if(*pHead == NULL)
	{
		*pHead = pTree;
	}
	else
	{
		(*pTail)->pRight = pTree;
		pTree->pLeft = *pTail;
	}
	*pTail = pTree;

	//右
	BSTToList(pTree->pRight,pHead,pTail);
}

void Print(BST *pHead)
{
	while(pHead)
	{
		printf("%d ",pHead->nValue);
		pHead = pHead->pRight;
	}
}

int main()
{
	int arr[] = {10,7,199,3,27,1,6,25,4};
	BST *pTree = CreateBST(arr,sizeof(arr)/sizeof(arr[0]));
	Traversal(pTree);
	printf("\n");
	BST *pHead = NULL;
	BST *pTail = NULL;
	BSTToList(pTree,&pHead,&pTail);
	Print(pHead);
	return 0;
}

红黑树:

额~~ 本人还未深刻了解各种情况,所以先放个源码 ,以后再填

#include
#include

enum COLOR{RED,BLACK};

typedef struct rbt
{
	int nValue;
	int nColor;
	struct rbt *pLeft;
	struct rbt *pRight;
	struct rbt *pFather;
}RBT;

RBT *pRBT = NULL;

void RightRotate(RBT **pTree)
{
	if(*pTree == NULL || (*pTree)->pLeft == NULL)return;

	RBT *pNode = *pTree;
	RBT *pMark = pNode->pLeft;

	//三个孩子关系
	pNode->pLeft = pMark->pRight;
	pMark->pRight = pNode;
	if(pNode->pFather != NULL)
	{
		if(pNode == pNode->pFather->pLeft)
		{
			pNode->pFather->pLeft = pMark;
		}
		else
		{
			pNode->pFather->pRight = pMark;
		}
	}
	else
	{
		//换根
		pRBT = pMark;
	}

	//三个父亲关系
	if(pNode->pLeft != NULL)
	{
		pNode->pLeft->pFather = pNode;
	}

	pMark->pFather = pNode->pFather;
	pNode->pFather = pMark;
}
void LeftRotate(RBT **pTree)
{
	if(*pTree == NULL || (*pTree)->pRight == NULL)return;

	RBT *pNode = *pTree;
	RBT *pMark = pNode->pRight;

	//三个孩子关系
	pNode->pRight = pMark->pLeft;
	pMark->pLeft = pNode;
	if(pNode->pFather != NULL)
	{
		if(pNode == pNode->pFather->pLeft)
		{
			pNode->pFather->pLeft = pMark;
		}
		else
		{
			pNode->pFather->pRight = pMark;
		}
	}
	else
	{
		//换根
		pRBT = pMark;
	}

	//三个父亲关系
	if(pNode->pRight != NULL)
	{
		pNode->pRight->pFather = pNode;
	}

	pMark->pFather = pNode->pFather;
	pNode->pFather = pMark;
}

RBT *Search(RBT *pTree,int nNum)
{
	if(pTree == NULL)return NULL;

	while(pTree)
	{
		if(pTree->nValue > nNum)
		{
			//左侧
			if(pTree->pLeft == NULL)
			{
				return pTree;
			}
			pTree = pTree->pLeft;
		}
		else if(pTree->nValue < nNum)
		{
			if(pTree->pRight == NULL)
			{
				return pTree;
			}
			pTree = pTree->pRight;
		}
		else
		{
			printf("data error.\n");
			exit(1);
		}
	}
}

RBT *GetUncle(RBT *pNode)
{
	if(pNode == pNode->pFather->pLeft)
	{
		return pNode->pFather->pRight;
	}
	else
	{
		return pNode->pFather->pLeft;
	}
}

void AddNode(RBT *pTree,int nNum)
{
	//查找
	RBT *pNode = NULL;
	pNode = Search(pTree,nNum);

	//申请空间
	RBT *pTemp = NULL;
	pTemp = (RBT*)malloc(sizeof(RBT));
	pTemp->nValue = nNum;
	pTemp->nColor = RED;
	pTemp->pFather = pNode;
	pTemp->pLeft = NULL;
	pTemp->pRight = NULL;

	//情况分析
	//1.空树
	if(pNode == NULL)
	{
		pRBT = pTemp;
		pRBT->nColor = BLACK;
		return;
	}

	//非空树
	//连接
	if(pTemp->nValue < pNode->nValue)
	{
		pNode->pLeft = pTemp;
	}
	else
	{
		pNode->pRight = pTemp;
	}
	
	//2.父亲是黑的
	if(pNode->nColor == BLACK)
	{
		return;
	}

	//3.父亲是红的
	RBT *pUncle = NULL;
	RBT *pGrandFather = NULL;
	
	while(pNode->nColor == RED)
	{
		pGrandFather = pNode->pFather;
		pUncle = GetUncle(pNode);

		//3.1叔叔是红色
		if(pUncle != NULL && pUncle->nColor == RED)
		{
			pNode->nColor = BLACK;
			pUncle->nColor = BLACK;
			pGrandFather->nColor = RED;

			pTemp = pGrandFather;
			pNode = pTemp->pFather;

			//根
			if(pNode == NULL)
			{
				pRBT->nColor = BLACK;
				break;
			}

			continue;
		}

		//3.2叔叔是黑的
		if(pUncle == NULL || pUncle->nColor == BLACK)
		{
			//3.2.1父亲是爷爷的左
			if(pNode == pGrandFather->pLeft)
			{
				//3.2.1.1当前节点是父亲的右
				if(pTemp == pNode->pRight)
				{
					pTemp = pNode;

					LeftRotate(&pTemp);

					pNode = pTemp->pFather;
				}

				//3.2.1.2当前节点是父亲的左侧
				if(pTemp == pNode->pLeft)
				{
					pNode->nColor = BLACK;
					pGrandFather->nColor = RED;

					RightRotate(&pGrandFather);
					break;
				}
			}

			//3.2.2父亲是爷爷的右
			if(pNode == pGrandFather->pRight)
			{
				//3.2.2.1当前节点是父亲的左
				if(pTemp == pNode->pLeft)
				{
					pTemp = pNode;

					RightRotate(&pTemp);

					pNode = pTemp->pFather;
				}

				//3.2.2.2当前节点是父亲的右
				if(pTemp == pNode->pRight)
				{
					pNode->nColor = BLACK;
					pGrandFather->nColor = RED;

					LeftRotate(&pGrandFather);
					break;
				}
			}
		}
	}
}

void CreateRBT(int arr[],int nLength)
{
	if(arr == NULL || nLength <= 0)return;

	int i;
	for(i = 0;inValue,pTree->nColor);

	Traversal(pTree->pLeft);
	Traversal(pTree->pRight);
}

RBT *FindNode(RBT *pTree,int nNum)
{
	if(pTree == NULL)return NULL;

	while(pTree)
	{
		if(pTree->nValue == nNum)
		{
			return pTree;
		}
		else if(pTree->nValue > nNum)
		{
			pTree = pTree->pLeft;
		}
		else
		{
			pTree = pTree->pRight;
		}
	}

	return NULL;
}

void DelNode(RBT *pTree,int nNum)
{
	//查找
	RBT *pTemp = NULL;
	pTemp = FindNode(pTree,nNum);

	if(pTemp == NULL)return;

	//分析孩子情况
	RBT *pMark = NULL;

	if(pTemp->pLeft != NULL && pTemp->pRight != NULL)
	{
		pMark = pTemp;

		pTemp = pTemp->pLeft;
		while(pTemp->pRight != NULL)
		{
			pTemp = pTemp->pRight;
		}

		//值覆盖
		pMark->nValue = pTemp->nValue;
	}

	//颜色
	RBT *pNode = pTemp->pFather;
	//1.根 且无孩子
	if(pNode == NULL && pTemp->pLeft == NULL && pTemp->pRight == NULL)
	{
		pRBT = NULL;
		free(pTemp);
		pTemp = NULL;
		return;
	}

	//2.根 且有一个红孩子
	if(pNode == NULL && (pTemp->pLeft != NULL || pTemp->pRight != NULL))
	{
		pRBT = pTemp->pLeft ? pTemp->pLeft : pTemp->pRight;
		pRBT->nColor = BLACK;
		pRBT->pFather = NULL;

		free(pTemp);
		pTemp = NULL;
		return;
	}

	//3.非根 红色 
	if(pTemp->nColor == RED)
	{
		if(pTemp == pNode->pLeft)
		{
			pNode->pLeft = NULL;
		}
		else
		{
			pNode->pRight = NULL;
		}
		free(pTemp);
		pTemp = NULL;
		return;
	}

	//4.非根 黑色 且有一个红孩子
	if(pTemp->nColor == BLACK && (pTemp->pLeft != NULL || pTemp->pRight != NULL))
	{
		if(pTemp == pNode->pLeft)
		{
			pNode->pLeft = pTemp->pLeft ? pTemp->pLeft:pTemp->pRight;
			pNode->pLeft->pFather = pNode;
			pNode->pLeft->nColor = BLACK;
		}
		else
		{
			pNode->pRight = pTemp->pLeft ? pTemp->pLeft:pTemp->pRight;
			pNode->pRight->pFather = pNode;
			pNode->pRight->nColor = BLACK;
		}

		free(pTemp);
		pTemp = NULL;
		return;
	}

	//5.非根 黑 且无孩子
	RBT *pBrother = GetUncle(pTemp);
	
	//假删除
	if(pTemp == pNode->pLeft)
	{
		pNode->pLeft = NULL;
	}
	else
	{
		pNode->pRight = NULL;
	}

	pMark = pTemp;

	while(1)
	{
		//5.1兄弟是红的
		if(pBrother->nColor == RED)
		{
			pBrother->nColor = BLACK;
			pNode->nColor = RED;

			//5.1.1兄弟是父亲的左
			if(pBrother == pNode->pLeft)
			{
				RightRotate(&pNode);
				pBrother = pNode->pLeft;
				continue;
			}

			//5.1.2兄弟是父亲的右
			if(pBrother == pNode->pRight)
			{
				LeftRotate(&pNode);
				pBrother = pNode->pRight;
				continue;
			}
		}

		//5.2兄弟是黑的
		if(pBrother->nColor == BLACK)
		{
			//5.2.1两个侄子全黑
			if((pBrother->pLeft == NULL && pBrother->pRight == NULL)||
				((pBrother->pLeft != NULL && pBrother->pLeft->nColor == BLACK)&&
				(pBrother->pRight != NULL && pBrother->pRight->nColor == BLACK)))
			{
				//5.2.1.1父亲是红的
				if(pNode->nColor == RED)
				{
					pNode->nColor = BLACK;
					pBrother->nColor = RED;
					break;
				}

				//5.2.1.2父亲是黑色的
				if(pNode->nColor == BLACK)
				{
					pBrother->nColor = RED;

					pTemp = pNode;
					pNode = pTemp->pFather;

					//根
					if(pNode == NULL)
					{
						break;
					}
					pBrother = GetUncle(pTemp);
					continue;
				}
			}

			//5.2.2左侄子红,右侄子黑
			if((pBrother->pLeft != NULL && pBrother->pLeft->nColor == RED)&&
				(pBrother->pRight == NULL || pBrother->pRight->nColor == BLACK))
			{
				//5.2.2.1兄弟是父亲的右
				if(pBrother == pNode->pRight)
				{
					pBrother->nColor = RED;
					pBrother->pLeft->nColor = BLACK;

					RightRotate(&pBrother);
					pBrother = pNode->pRight;
					continue;
				}

				//5.2.2.2兄弟是父亲的左
				if(pBrother == pNode->pLeft)
				{
					pBrother->nColor = pNode->nColor;
					pNode->nColor = BLACK;
					pBrother->pLeft->nColor = BLACK;

					RightRotate(&pNode);
					break;
				}
			}

			//5.2.3右侄子是红
			if(pBrother->pRight != NULL && pBrother->pRight->nColor == RED)
			{
				//5.2.3.1兄弟是父亲的左
				if(pBrother == pNode->pLeft)
				{
					pBrother->nColor = RED;
					pBrother->pRight->nColor = BLACK;

					LeftRotate(&pBrother);
					pBrother = pNode->pLeft;
					continue;
				}

				//5.2.3.2兄弟是父亲的右
				if(pBrother == pNode->pRight)
				{
					pBrother->nColor = pNode->nColor;
					pNode->nColor = BLACK;
					pBrother->pRight->nColor = BLACK;

					LeftRotate(&pNode);
					break;
				}
			}
		}
	}
	free(pMark);
	pMark = NULL;
}

int main()
{
	int arr[] = {11,2,14,1,7,15,5,8};
	CreateRBT(arr,sizeof(arr)/sizeof(arr[0]));
	Traversal(pRBT);
	printf("---------------------------\n");
	//AddNode(pRBT,4);
	//Traversal(pRBT);
	DelNode(pRBT,1);
	Traversal(pRBT);
	printf("---------------------------\n");
	DelNode(pRBT,11);
	Traversal(pRBT);
	printf("---------------------------\n");
	DelNode(pRBT,15);
	Traversal(pRBT);
	printf("---------------------------\n");
	DelNode(pRBT,2);
	Traversal(pRBT);
	printf("---------------------------\n");

	return 0;
}

你可能感兴趣的:(数据结构)