本文是小编巩固自身而作,如有错误,欢迎指出!
1.栈
1.1 概念与结构
栈:⼀种特殊的线性表,其只允许在固定的⼀端进⾏插⼊和删除元素操作。进⾏数据插⼊和删除操作的⼀端称为栈顶,另⼀端称为栈底。栈中的数据元素遵守后进先出的原则。
栈的实现⼀般可以使⽤数组或者链表实现,相对⽽⾔数组的结构实现更优⼀些。因为数组在尾上插⼊ 数据的代价⽐较⼩。(在之前我们学过,数组的尾插时间复杂度是O(1),而链表的复杂度是O(N))
1.2栈的实现
1.2.1栈的结构
//定义栈的结构
typedef int stdatatype;
struct Stack
{
stdatatype* arr;
int top;//指向栈顶
int capacity;//栈的容量
};
typedef struct Stack ST;
这里的栈我们采用类似于顺序表的方式实现,一个栈包含如上码所示的三个内容。
1.2.2栈的初始化
和顺序表类似,将数组置空,数据置零。
void stackinit(ST* ps)//栈初始化
{
ps->arr = NULL;
ps->top = ps->capacity = 0;
}
1.2.3入栈
void stackpush(ST* ps, stdatatype x)//入栈
{
if (ps->top == ps->capacity)//栈满了
{
//增容
int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
stdatatype* tmp = (stdatatype*)realloc(ps->arr, newcapacity*sizeof(stdatatype));
if (tmp == NULL)
{
perror("realloc fail");
exit(1);
}
ps->arr = tmp;
ps->capacity = newcapacity;
}
//栈未满
ps->arr[ps->top++] = x;
}
1.2.4出栈
void stackpop(ST* ps)//出栈
{
assert(!stackempty(ps));//判空
--ps->top;
}
在出栈时需要考虑是否为空的情况我们这里使用bool函数。
bool stackempty(ST* ps)
{
assert(ps);
return ps->top == 0;
}
1.2.5取栈顶元素
stdatatype stacktop(ST* ps)//取栈顶元素
{
assert(!stackempty(ps));
return ps->arr[ps->top - 1];
}
1.2.6销毁栈
void stackdestroy(ST* ps)//销毁栈
{
if (ps->arr)
{
free(ps->arr);
ps->arr = NULL;
ps->top = ps->capacity = 0;
}
}
1.3完整代码实现
.h文件
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
//定义栈的结构
typedef int stdatatype;
struct Stack
{
stdatatype* arr;
int top;//指向栈顶
int capacity;//栈的容量
};
typedef struct Stack ST;
void stackinit(ST* ps);//栈初始化
void stackpush(ST* ps, stdatatype x);//入栈
void stackpop(ST* ps);//出栈
bool stackempty(ST* ps);//判空
stdatatype stacktop(ST* ps);//取栈顶元素
void stackdestroy(ST* ps);//销毁栈
.c文件
#define _CRT_SECURE_NO_WARNINGS
#include"stack.h"
void stackinit(ST* ps)//栈初始化
{
ps->arr = NULL;
ps->top = ps->capacity = 0;
}
void stackpush(ST* ps, stdatatype x)//入栈
{
if (ps->top == ps->capacity)
{
//增容
int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
stdatatype* tmp = (stdatatype*)realloc(ps->arr, newcapacity*sizeof(stdatatype));
if (tmp == NULL)
{
perror("realloc fail");
exit(1);
}
ps->arr = tmp;
ps->capacity = newcapacity;
}
ps->arr[ps->top++] = x;
}
bool stackempty(ST* ps)
{
assert(ps);
return ps->top == 0;
}
void stackpop(ST* ps)//出栈
{
assert(!stackempty(ps));//判空
--ps->top;
}
stdatatype stacktop(ST* ps)//取栈顶元素
{
assert(!stackempty(ps));
return ps->arr[ps->top - 1];
}
void stackdestroy(ST* ps)//销毁栈
{
if (ps->arr)
{
free(ps->arr);
ps->arr = NULL;
ps->top = ps->capacity = 0;
}
}
.c文件(测试)
#define _CRT_SECURE_NO_WARNINGS
#include"stack.h"
void test01()
{
ST st;
stackinit(&st);
stackpush(&st, 1);
stackpush(&st, 2);
stackpush(&st, 3);
stackpush(&st, 4);
stackpop(&st);
while (!stackempty(&st))
{
int top = stacktop(&st);
printf("%d ", top);
stackpop(&st);
}
}
int main()
{
test01();
return 0;
}
2.队列
2.1概念与结构
概念:只允许在⼀端进⾏插⼊数据操作,在另⼀端进⾏删除数据操作的特殊线性表,队列具有先进先出。
队列也可以数组和链表的结构实现,使⽤链表的结构实现更优⼀些,因为如果使⽤数组的结构,出队 列在数组头上出数据,效率会比较低。
2.2队列的实现
2.2.1队列的结构
typedef int QDdatatype;
//节点结构
typedef struct QueueNode
{
QDdatatype data;
struct QueueNode* next;
}QUnode;
//队列结构
typedef struct Queue
{
struct QueueNode* phead;
struct QueueNode* ptail;
//int size;//有效数据的个数
}QU;
为了避免像一般单链表在尾部进行操作导致时间复杂度增加,我们相较于单链表多创建一个尾节点 。
2.2.2队列的初始化
void QUinit(QU* pq)//初始化
{
assert(pq);
pq->phead = pq->ptail = NULL;
//pq->size = 0;
}
2.2.3入队--队尾
void QUpushi(QU* pq, QDdatatype x)//入队--队尾
{
assert(pq);
//队列为空
QUnode* newnode = (QUnode*)malloc(sizeof(QUnode));
if (newnode == NULL)
{
perror("malloc fail");
exit(1);
}
newnode->data = x;
newnode->next = NULL;
if (pq->phead == NULL)
{
pq->phead = pq->ptail = newnode;
}
else
{
pq->ptail->next = newnode;
pq->ptail = pq->ptail->next;
}
//pq->size++;
}
类似于链表中尾插。
2.2.4出队--队头
void QUpop(QU * pq)//出队--队头
{
assert(!QUempty(pq));
//只有一个节点
if (pq->phead == pq->ptail)
{
free(pq->phead);
pq->phead = pq->ptail = NULL;
}
else
{
QUnode* next = pq->phead->next;
free(pq->phead);
pq->phead = next;
}
/*pq->size--;*/
}
在出队时就要考虑队列为空的情况
bool QUempty(QU* pq)//队列判空
{
assert(pq);
return pq->phead == NULL;
}
2.2.5 取头、尾数据
QDdatatype QUfront(QU* pq)//取头数据
{
assert(!QUempty(pq));
return pq->phead->data;
}
QDdatatype QUback(QU* pq)//取尾数据
{
assert(!QUempty(pq));
return pq->ptail->data;
}
2.2.6销毁队列
void QUdestroy(QU* pq)//销毁队列
{
assert(pq);
QUnode* pcur = pq->phead;
while (pcur)
{
QUnode* next = pq->phead;
free(pcur);
pcur = next;
}
pq->phead = pq->ptail = NULL;
/*pq->size = 0;*/
}
2.3完整代码实现
.h文件
#pragma once
#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
#include<assert.h>
typedef int QDdatatype;
//节点结构
typedef struct QueueNode
{
QDdatatype data;
struct QueueNode* next;
}QUnode;
//队列结构
typedef struct Queue
{
struct QueueNode* phead;
struct QueueNode* ptail;
//int size;//有效数据的个数
}QU;
void QUinit(QU* pq);//初始化
void QUpushi(QU* pq, QDdatatype x);//入队--队尾
void QUpop(QU* pq);//出队--队头
bool QUempty(QU* pq);//队列判空
QDdatatype QUfront(QU* pq);//取头数据
QDdatatype QUback(QU* pq);//取尾数据
void QUdestroy(QU* pq);//销毁队列
int QUsize(QU* pq);//队列的有效元素
.c文件
#define _CRT_SECURE_NO_WARNINGS
#include"Queue.h"
void QUinit(QU* pq)//初始化
{
assert(pq);
pq->phead = pq->ptail = NULL;
//pq->size = 0;
}
bool QUempty(QU* pq)//队列判空
{
assert(pq);
return pq->phead == NULL;
}
void QUpushi(QU* pq, QDdatatype x)//入队--队尾
{
assert(pq);
//队列为空
QUnode* newnode = (QUnode*)malloc(sizeof(QUnode));
if (newnode == NULL)
{
perror("malloc fail");
exit(1);
}
newnode->data = x;
newnode->next = NULL;
if (pq->phead == NULL)
{
pq->phead = pq->ptail = newnode;
}
else
{
pq->ptail->next = newnode;
pq->ptail = pq->ptail->next;
}
//pq->size++;
}
void QUpop(QU * pq)//出队--队头
{
assert(!QUempty(pq));
//只有一个节点
if (pq->phead == pq->ptail)
{
free(pq->phead);
pq->phead = pq->ptail = NULL;
}
else
{
QUnode* next = pq->phead->next;
free(pq->phead);
pq->phead = next;
}
/*pq->size--;*/
}
QDdatatype QUfront(QU* pq)//取头数据
{
assert(!QUempty(pq));
return pq->phead->data;
}
QDdatatype QUback(QU* pq)//取尾数据
{
assert(!QUempty(pq));
return pq->ptail->data;
}
void QUdestroy(QU* pq)//销毁队列
{
assert(pq);
QUnode* pcur = pq->phead;
while (pcur)
{
QUnode* next = pq->phead;
free(pcur);
pcur = next;
}
pq->phead = pq->ptail = NULL;
/*pq->size = 0;*/
}
int QUsize(QU* pq)//队列的有效元素
{
/*assert(pq);
QUnode* pcur = pq->phead;
int size = 0;
while (pcur)
{
size++;
pcur = pcur->next;
}*/
/*return pq->size;*/
}
.c文件(测试)
#define _CRT_SECURE_NO_WARNINGS
#include"Queue.h"
void test01()
{
QU q;
QUinit(&q);
QUpushi(&q, 1);
QUpushi(&q, 2);
QUpushi(&q, 3);
QUpop(&q);
int front = QUfront(&q);
int back = QUback(&q);
printf("%d\n", front);
printf("%d\n", back);
void QUdestroy(QU * pq);//销毁队列
}
int main()
{
test01();
return 0;
}
在具体实现思路都与之前的顺序表与链表相似,有不理解的可以看看前篇
本次分享就到这里结束了,感谢阅读!