栈: 推荐由线性表实现。
分为栈顶和栈底
栈的特点: 后进先出且只能从栈顶出数据
栈的结构
#define STData int
typedef struct STNode
{
STData* arr;
int size;
int capacity;
}STNode;
接口
void STInit(STNode* st);
void STDestroy(STNode* st);
void STPush(STNode* st , STData x);
void STPop(STNode* st);
bool STEmpty(STNode* st);
STData STTop(STNode* st);
接口的实现
void STInit(STNode* st)
{
st->arr = NULL;
st->capacity = st->size = 0;
return;
}
void STDestroy(STNode* st)
{
assert(st);
assert(!STEmpty(st));
free(st->arr);
st->arr = NULL;
st->capacity = st->size = 0;
}
void STPush(STNode* st, STData x)
{
assert(st);
//不满
if (st->size == st->capacity)
{
int newcapacity = st->capacity == 0 ? 4 : 2 * st->capacity;
STData* arr = (STData*)realloc(st->arr, sizeof(STData) * newcapacity);
if (arr == NULL)
{
perror("STPush::malloc(arr)");
exit(1);
}
st->arr = arr;
st->capacity = newcapacity;
}
st->arr[st->size++] = x;
}
void STPop(STNode* st)
{
assert(st);
assert(!STEmpty(st));
st->size--;
}
bool STEmpty(STNode* st)
{
assert(st);
return st->size == 0;
}
STData STTop(STNode* st)
{
assert(st);
assert(!STEmpty(st));
return st->arr[(st->size)-1];
}
int STSize(STNode* st)
{
assert(st);
assert(!STEmpty(st));
return st->size;
}
队列:有队头和队尾
实现先进先出且只能从队头出数据
队列的结构
#define QData BTNode*
typedef struct QueNode
{
QData val;
struct QueNode* next;
}QNode;
typedef struct Queue
{
//指向队头
QNode* phead;
//指向队尾
QNode* ptail;
int size;
}Queue;
接口
void QueueInit(Queue* pq);
void QueueDestroy(Queue* pq);
void QueuePush(Queue* pq, QData x);
void QueuePop(Queue* pq);
QData QueueFront(Queue* pq);
int QueueSize(Queue* pq);
bool QueueEmpty(Queue* pq);
QData QueueBack(Queue* pq);
接口的实现
void QueueInit(Queue* pq)
{
pq->phead = pq->ptail = NULL;
pq->size = 0;
}
void QueueDestroy(Queue* pq)
{
assert(pq);
QNode* pn = pq->phead;
while (pn)
{
pn = pq->phead->next;
free(pq->phead);
pq->phead = pn;
}
pq->phead = pq->ptail = NULL;
pq->size = 0;
}
void QueuePush(Queue* pq, QData x)
{
assert(pq);
QNode* qn = (QNode*)malloc(sizeof(QNode));
if (qn == NULL)
{
perror("QueuePush::malloc(qn)");
exit(1);
}
qn->val = x;
qn->next = NULL;
if (QueueEmpty(pq))
{
pq->phead = pq->ptail = qn;
}
else
{
pq->ptail->next = qn;
pq->ptail = qn;
}
pq->size++;
}
void QueuePop(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
//只有一个节点的时候
if (pq->phead == pq->ptail)
{
free(pq->phead);
pq->phead = pq->ptail = NULL;
}
else
{
QNode* pn = pq->phead->next;
free(pq->phead);
pq->phead = pn;
}
pq->size--;
}
QData QueueFront(Queue* pq)
{
return pq->phead->val;
}
int QueueSize(Queue* pq)
{
return pq->size;
}
bool QueueEmpty(Queue* pq)
{
return pq->size == 0;
}
QData QueueBack(Queue* pq)
{
return pq->ptail->val;
}
堆: 实质上是线性表实现的一个二叉树结构
堆的结构
#define HPData int
typedef struct HPNode
{
HPData* arr;
int size;
int capacity;
}HPNode;
接口(向上调整和向下调整在接口实现处包含)
void HPCreat(HPNode* hp, HPData* arr, int n);
void HPInit(HPNode* hp);
void HPDestroy(HPNode* hp);
void HPPush(HPNode* hp, HPData x);
void HPPop(HPNode* hp);
HPData HPTop(HPNode* hp);
bool HPEmpty(HPNode* hp);
int HPSize(HPNode* hp);
接口的实现
void swap(int* a, int* b)
{
int s = *a;
*a = *b;
*b = s;
}
//向上调整
void AdjustUp(HPData* arr, int size)
{
assert(arr);
int child = size - 1;
int parent = (child - 1) / 2;
while (child > 0)
{
if (arr[child] <= arr[parent])
{
swap(&arr[child], &arr[parent]);
child = parent;
parent = (child - 1) / 2;
}
else
break;
}
}
//向下调整
void AdjustDown(HPData* arr, int size)
{
assert(arr);
int parent = 0;
int child = parent * 2 + 1;
while (child < size)
{
if (child + 1 < n && arr[child + 1] < arr[child])
{
child = child + 1;
}
if (arr[parent] >= arr[child])
{
swap(&arr[parent], &arr[child]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void HPInit(HPNode* hp)
{
hp->arr = NULL;
hp->size = hp->capacity = 0;
}
void HPDestroy(HPNode* hp);
void HPPush(HPNode* hp, HPData x)
{
assert(hp);
//空间不足
if (hp->size == hp->capacity)
{
int newcapacity = hp->capacity == 0 ? 4 : 2 * hp->capacity;
HPData* arr = (HPData*)realloc(hp->arr,sizeof(HPData) * newcapacity);
if (arr == NULL)
{
perror("HPPush::malloc(arr)");
exit(1);
}
hp->arr = arr;
hp->capacity = newcapacity;
}
hp->arr[hp->size++] = x;
//向上调整
int child = hp->size - 1;
int parent = (child - 1) / 2;
while (child > 0)
{
if (hp->arr[child] <= hp->arr[parent])
{
swap(&hp->arr[child], &hp->arr[parent]);
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
//堆的删除是删除根节点
void HPPop(HPNode* hp)
{
assert(hp);
assert(!HPEmpty(hp));
swap(&hp->arr[0], &hp->arr[hp->size - 1]);
hp->size--;
AdjustDown(hp->arr, hp->size);
}
HPData HPTop(HPNode* hp)
{
assert(hp);
return hp->arr[0];
}
bool HPEmpty(HPNode* hp)
{
assert(hp);
return hp->size == 0;
}
int HPSize(HPNode* hp)
{
return hp->size;
}
树: 此处是指二叉树。
二叉树的结构
#define BTData char
typedef struct BTNode
{
BTData val;
struct BTNode* left;//左孩子
struct BTNode* right;//右孩子
}BTNode;
接口
BTNode* BTCreat(BTData* arr, int n, int* pi);
void BTDestroy(BTNode* root);
int BTSize(BTNode* root);
int BTLeafSize(BTNode* root);
int BTKLeafSize(BTNode* root , int k);
BTNode* BTFind(BTNode* root, BTData x);
void BTPrevOrder(BTNode* root);
void BTInOrder(BTNode* root);
void BTPostOrder(BTNode* root);
void BTLeveOrder(BTNode* root);
bool BTEmpty(BTNode* root);
接口的实现
// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BTCreat(BTData* arr, int n, int* pi)
{
assert(arr);
if (arr[*pi] == '#')
{
(*pi)++;
return NULL;
}
BTNode* root = (BTNode*)malloc(sizeof(BTNode));
if (root == NULL)
{
perror("BTCreat::malloc(root)");
exit(1);
}
root->val = arr[(*pi)++];
root->left = BTCreat(arr, n, pi);
root->right = BTCreat(arr, n, pi);
return root;
}
void BTDestroy(BTNode* root)
{
Queue pq = { 0 };
QueueInit(&pq);
QueuePush(&pq, root);
BTNode* bt = root;
while (!QueueEmpty(&pq))
{
BTNode* bl = QueueFront(&pq);
if (bl != NULL)
{
printf("%c ", bl->val);
QueuePop(&pq);
QueuePush(&pq, bt->left);
QueuePush(&pq, bt->right);
free(bt);
}
else
{
printf("# ");
QueuePop(&pq);
}
if (!QueueEmpty(&pq))
bt = QueueFront(&pq);
}
}
int BTSize(BTNode* root)
{
if (root == NULL)
return 0;
return BTSize(root->left) + BTSize(root->right) + 1;
}
int BTLeafSize(BTNode* root)
{
if (root == NULL) return 0;
if (root->left == NULL && root->right == NULL) return 1;
return BTLeafSize(root->left) + BTLeafSize(root->right);
}
int BTKLeafSize(BTNode* root, int k)
{
if (root == NULL)
{
return 0;
}
if (k == 1)
{
return 1;
}
return BTKLeafSize(root->left, k - 1) + BTKLeafSize(root->right, k - 1);
}
BTNode* BTFind(BTNode* root, BTData x)
{
if (root == NULL) return NULL;
if (root->val == x) return root;
else
{
BTNode* left = BTFind(root->left, x);
BTNode* right = BTFind(root->right, x);
if (left != NULL)
{
return left;
}
else
{
return right;
}
}
}
void BTPrevOrder(BTNode* root)
{
if (root == NULL)
{
printf("# ");
return;
}
printf("%c ", root->val);
BTPrevOrder(root->left);
BTPrevOrder(root->right);
}
void BTInOrder(BTNode* root)
{
if (root == NULL)
{
printf("# ");
return;
}
BTPrevOrder(root->left);
printf("%c ", root->val);
BTPrevOrder(root->right);
}
void BTPostOrder(BTNode* root)
{
if (root == NULL)
{
printf("# ");
return;
}
BTPrevOrder(root->left);
BTPrevOrder(root->right);
printf("%c ", root->val);
}
void BTLeveOrder(BTNode* root)
{
Queue pq = { 0 };
QueueInit(&pq);
QueuePush(&pq, root);
BTNode* bt = root;
while (!QueueEmpty(&pq))
{
BTNode* bl = QueueFront(&pq);
if (bl != NULL)
{
printf("%c ", bl->val);
QueuePop(&pq);
QueuePush(&pq, bt->left);
QueuePush(&pq, bt->right);
}
else
{
printf("# ");
QueuePop(&pq);
}
if(!QueueEmpty(&pq))
bt = QueueFront(&pq);
}
}
bool BTEmpty(BTNode* root)
{
return root == NULL;
}