9. avltree
fatal.h
#include <stdio.h>
#include <stdlib.h>
#define Error(Str) FatalError(Str)
#define FatalError(Str) fprintf(stderr, "%s\n", Str), exit(1)
avltree.h
typedef int ElementType;
#ifndef _AvlTree_H
#define _AvlTree_H
struct AvlNode;
typedef struct AvlNode *Position;
typedef struct AvlNode *AvlTree;
AvlTree MakeEmpty(AvlTree T);
Position Find(ElementType X, AvlTree T);
Position FindMin(AvlTree T);
Position FindMax(AvlTree T);
AvlTree Insert(ElementType X, AvlTree T);
AvlTree Delete(ElementType X, AvlTree T);
ElementType Retrieve(Position P);
void PreorderTraversal(AvlTree T);
void InorderTraversal(AvlTree T);
void PostorderTraversal(AvlTree T);
void LevelorderTraversal(AvlTree T);
#endif /* _AvlTree_H */
queue.h
#ifndef _Queue_h
#define _Queue_h
struct QueueRecord;
typedef struct QueueRecord *Queue;
int IsEmptyQueue(Queue Q);
int IsFullQueue(Queue Q);
Queue CreateQueue(int MaxElements);
void DisposeQueue(Queue Q);
void MakeEmptyQueue(Queue Q);
void Enqueue(AvlTree X, Queue Q);
AvlTree Front(Queue Q);
void Dequeue(Queue Q);
AvlTree FrontAndDequeue(Queue Q);
#endif
avltree.c
#include "avltree.h"
#include "queue.h"
#include <stdlib.h>
#include "fatal.h"
struct AvlNode
{
ElementType Element;
AvlTree Left;
AvlTree Right;
int Height;
};
AvlTree MakeEmpty(AvlTree T)
{
if (T != NULL)
{
MakeEmpty(T->Left);
MakeEmpty(T->Right);
free(T);
}
return NULL;
}
Position Find(ElementType X, AvlTree T)
{
if (T == NULL)
return NULL;
if (X < T->Element)
return Find(X, T->Left);
else if (X > T->Element)
return Find(X, T->Right);
else
return T;
}
Position FindMin(AvlTree T)
{
if (T == NULL)
return NULL;
else if (T->Left == NULL)
return T;
else
return FindMin(T->Left);
}
Position FindMax(AvlTree T)
{
if (T != NULL)
while (T->Right != NULL)
T = T->Right;
return T;
}
static int Height(Position P)
{
if (P == NULL)
return -1;
else
return P->Height;
}
static int Max(int Lhs, int Rhs)
{
return Lhs > Rhs ? Lhs : Rhs;
}
/* This function can be called only if K2 has a left child */
/* Perform a rotate between a node (K2) and its left child */
/* Update heights, then return new root */
static Position SingleRotateWithLeft(Position K2)
{
Position K1;
K1 = K2->Left;
K2->Left = K1->Right;
K1->Right = K2;
K2->Height = Max(Height(K2->Left), Height(K2->Right)) + 1;
K1->Height = Max(Height(K1->Left), K2->Height) + 1;
return K1; /* New root */
}
/* This function can be called only if K1 has a right child */
/* Perform a rotate between a node (K1) and its right child */
/* Update heights, then return new root */
static Position SingleRotateWithRight(Position K1)
{
Position K2;
K2 = K1->Right;
K1->Right = K2->Left;
K2->Left = K1;
K1->Height = Max(Height(K1->Left), Height(K1->Right)) + 1;
K2->Height = Max(Height(K2->Right), K1->Height) + 1;
return K2; /* New root */
}
/* This function can be called only if K3 has a left */
/* child and K3's left child has a right child */
/* Do the left-right double rotation */
/* Update heights, then return new root */
static Position DoubleRotateWithLeft(Position K3)
{
/* Rotate between K1 and K2 */
K3->Left = SingleRotateWithRight(K3->Left);
/* Rotate between K3 and K2 */
return SingleRotateWithLeft(K3);
}
/* This function can be called only if K1 has a right */
/* child and K1's right child has a left child */
/* Do the right-left double rotation */
/* Update heights, then return new root */
static Position DoubleRotateWithRight(Position K1)
{
/* Rotate between K3 and K2 */
K1->Right = SingleRotateWithLeft(K1->Right);
/* Rotate between K1 and K2 */
return SingleRotateWithRight(K1);
}
AvlTree Insert(ElementType X, AvlTree T)
{
if (T == NULL)
{
/* Create and return a one-node tree */
T = malloc(sizeof(struct AvlNode));
if (T == NULL)
FatalError("Out of space!!!");
else
{
T->Element = X; T->Height = 0;
T->Left = T->Right = NULL;
}
}
else if (X < T->Element)
{
T->Left = Insert(X, T->Left);
if (Height(T->Left) - Height(T->Right) == 2)
{
if (X < T->Left->Element)
T = SingleRotateWithLeft(T);
else
T = DoubleRotateWithLeft(T);
}
}
else if (X > T->Element)
{
T->Right = Insert(X, T->Right);
if (Height(T->Right) - Height(T->Left) == 2)
{
if (X > T->Right->Element)
T = SingleRotateWithRight(T);
else
T = DoubleRotateWithRight(T);
}
}
/* Else X is in the tree already; we'll do nothing */
T->Height = Max(Height(T->Left), Height(T->Right)) + 1;
return T;
}
AvlTree Delete(ElementType X, AvlTree T)
{
Position TmpCell;
if (T == NULL)
Error("Element not found");
else if (X < T->Element) /* Go left */
T->Left = Delete(X, T->Left);
else if (X > T->Element) /* Go right */
T->Right = Delete(X, T->Right);
/* Found element to be deleted */
else if (T->Left && T->Right) /* Two children */
{
/* Replace with smallest in right subtree */
TmpCell = FindMin(T->Right);
T->Element = TmpCell->Element;
T->Right = Delete(T->Element, T->Right);
}
else /* One or zero children */
{
TmpCell = T;
if (T->Left == NULL) /* Also handles 0 children */
T = T->Right;
else if (T->Right == NULL)
T = T->Left;
free(TmpCell);
}
if (T != NULL)
{
if (Height(T->Left) - Height(T->Right) == 2)
{
if (Height(T->Left->Left) >= Height(T->Left->Right))
T = SingleRotateWithLeft(T);
else
T = DoubleRotateWithLeft(T);
}
else if (Height(T->Right) - Height(T->Left) == 2)
{
if (Height(T->Right->Right) >= Height(T->Right->Left))
T = SingleRotateWithRight(T);
else
T = DoubleRotateWithRight(T);
}
T->Height = Max(Height(T->Left), Height(T->Right)) + 1;
}
return T;
}
ElementType Retrieve(Position P)
{
return P->Element;
}
void PreorderTraversal(AvlTree T)
{
if (T != NULL)
{
printf("%d\t", T->Element);
PreorderTraversal(T->Left);
PreorderTraversal(T->Right);
}
}
void InorderTraversal(AvlTree T)
{
if (T != NULL)
{
InorderTraversal(T->Left);
printf("%d\t", T->Element);
InorderTraversal(T->Right);
}
}
void PostorderTraversal(AvlTree T)
{
if (T != NULL)
{
PostorderTraversal(T->Left);
PostorderTraversal(T->Right);
printf("%d\t", T->Element);
}
}
void LevelorderTraversal(AvlTree T)
{
Queue Q;
AvlTree TmpCell;
if (T == NULL)
return;
Q = CreateQueue(80);
Enqueue(T, Q);
while (!IsEmptyQueue(Q))
{
TmpCell = FrontAndDequeue(Q);
printf("%d\t", TmpCell->Element);
if (TmpCell->Left != NULL)
Enqueue(TmpCell->Left, Q);
if (TmpCell->Right != NULL)
Enqueue(TmpCell->Right, Q);
}
}
queue.c
#include "avltree.h"
#include "queue.h"
#include "fatal.h"
#include <stdlib.h>
#define MinQueueSize ( 5 )
struct QueueRecord
{
int Capacity;
int Front;
int Rear;
int Size;
AvlTree *Array;
};
int IsEmptyQueue(Queue Q)
{
return Q->Size == 0;
}
int IsFullQueue(Queue Q)
{
return Q->Size == Q->Capacity;
}
Queue CreateQueue(int MaxElements)
{
Queue Q;
if (MaxElements < MinQueueSize)
Error("Queue size is too small");
Q = malloc(sizeof(struct QueueRecord));
if (Q == NULL)
FatalError("Out of space!!!");
Q->Array = malloc(sizeof(AvlTree) * MaxElements);
if (Q->Array == NULL)
FatalError("Out of space!!!");
Q->Capacity = MaxElements;
MakeEmptyQueue(Q);
return Q;
}
void MakeEmptyQueue(Queue Q)
{
Q->Size = 0;
Q->Front = 1;
Q->Rear = 0;
}
void DisposeQueue(Queue Q)
{
if (Q != NULL)
{
free(Q->Array);
free(Q);
}
}
static int Succ(int Value, Queue Q)
{
if (++Value == Q->Capacity)
Value = 0;
return Value;
}
void Enqueue(AvlTree X, Queue Q)
{
if (IsFullQueue(Q))
Error("Full queue");
else
{
Q->Size++;
Q->Rear = Succ(Q->Rear, Q);
Q->Array[Q->Rear] = X;
}
}
AvlTree Front(Queue Q)
{
if (!IsEmptyQueue(Q))
return Q->Array[Q->Front];
Error("Empty queue");
return 0; /* Return value used to avoid warning */
}
void Dequeue(Queue Q)
{
if (IsEmptyQueue(Q))
Error("Empty queue");
else
{
Q->Size--;
Q->Front = Succ(Q->Front, Q);
}
}
AvlTree FrontAndDequeue(Queue Q)
{
AvlTree X = 0;
if (IsEmptyQueue(Q))
Error("Empty queue");
else
{
Q->Size--;
X = Q->Array[Q->Front];
Q->Front = Succ(Q->Front, Q);
}
return X;
}
testavl.c
#include "avltree.h"
#include "queue.h"
#include <stdio.h>
int main()
{
AvlTree T;
int i;
int j = 0;
T = MakeEmpty(NULL);
printf("Insert:\n");
for (i = 0; i < 50; i++, j = (j + 7) % 50)
{
printf("%d\t", j);
T = Insert(j, T);
}
printf("\n先序遍历:\n");
PreorderTraversal(T);
printf("\n中序遍历:\n");
InorderTraversal(T);
printf("\n后序遍历:\n");
PostorderTraversal(T);
printf("\n层序遍历:\n");
LevelorderTraversal(T);
printf("\n\n");
printf("Delete:\n");
for (i = 0; i < 50; i += 2)
{
printf("%d\t", i);
T = Delete(i, T);
}
printf("\n先序遍历:\n");
PreorderTraversal(T);
printf("\n中序遍历:\n");
InorderTraversal(T);
printf("\n后序遍历:\n");
PostorderTraversal(T);
printf("\n层序遍历:\n");
LevelorderTraversal(T);
printf("\n\n");
printf("Min is %d, Max is %d\n", Retrieve(FindMin(T)), Retrieve(FindMax(T)));
return 0;
}