栈和队列的实现

栈的概念

栈也是线性表的一种,但是栈只允许在固定的一端进行插入与删除数据,而进行插入与删除的一端统一称为栈顶,而另一端就称为栈底。简称:后进先出

压栈(push):将数据插入栈顶。

出栈(pop):将栈顶的数据删除。

栈的实现

栈和队列的实现_第1张图片

 栈存储与删除数据的形式是:后进先出。所以这就很符合顺序表的实现模式,可以快速地找到最后一个元素。如果用单链表的话就需要遍历显得比较复杂,但是将单链表的栈顶与栈底换一下也显得比较容易了。

需要实现的函数

typedef struct stack
{
	int* arr;//指向动态开辟的空间
	int top;//指向栈顶数据的下一个空间(表示实际数据个数)
	int capacity;//开辟空间的容量大小

}St;

void Inite(St* ps);//初始化
void Push(St* ps,int x);//压栈
void Pop(St* ps);//出栈
void Destroy(St* ps);//释放空间
int Top(St* ps);//返回栈顶元素

void Inite(St* ps)
{
	ps->arr = NULL;
	ps->capacity = 0;//容量大小
	ps->top = 0;//栈中存储元素个数

}

void Push(St* ps,int x)
{
	if (ps->capacity == ps->top)//判断容量是否足够
	{
		ps->capacity = ps->capacity == 0 ? 3 : 2 * ps->capacity;
		int* new = (int*)realloc(ps->arr,ps->capacity*sizeof(int));当ps->arr为空时realloc就相当于malloc
		if (new == NULL)
		{ 
			perror("realloc false:");
			return;
		}
		ps->arr = new;
		 
	}
	ps->arr[ps->top] = x;
	ps->top++;
}

void Pop(St* ps)//删除数据要考虑是否存在数据
{
	assert(ps->top);//ps->top为假就跳出
	ps->top--;

}

int Top(St* ps)
{
	assert(ps->top);//无数据时就跳出
	return ps->arr[ps->top-1];//top-1是栈顶的元素
}

void Destroy(St* ps)
{
	free(ps->arr);//free的对象是动态开辟的空间
	ps->capacity = ps->top = 0;
	ps->arr = NULL;
}

队列

队列的概念

队列同样也是线性表的一种,队列就像食堂打饭一样,前面的打好饭先走,新来的同学站在后面排队。即:只允许在一端进行插入数据,而另一端进行删除数据。

入队列:进行插入操作的一端称为队尾

出队列:进行删除操作的一端称为队头

队列的实现 

栈和队列的实现_第2张图片

队列是在对头删除数据,队尾插入数据,如果再用线性表来实现的话就会发生挪动数据的现象,效率会降低,所以我们选择更简便的方法,单链表实现队列。但是既然是尾入头删的模式,所以我们为了避免每次插入数据是找尾,所以我们每次插入数据的时候都记录上尾的位置就显得更容易了。

实现前的基本操作

typedef struct QueueNode//每个节点所具备的结构(多个节点)
{
	int val;
	struct Node* next;
}QNode;

typedef struct Queue//(只有一个)可以避免使用二级指针
{
	QNode* head;//记录节点头
	QNode* tail;//记录节点尾
	int size;//记录节点个数
}Que;

这里创建了两个结构体类型,一个是节点结构体。而我们既然又要记录尾的位置还要保存头的位置,所以我们又可以将这几个数据放在同一个结构体里,这里不仅仅在函数传参时方便了很多,而且不需要用到二级指针,所以我们每次传参时,传队列创建的变量地址就可以了。

函数的实现

void Init(Que* q);// 初始化队列

void Push(Que* q, int data);// 队尾入队列

void Pop(Que* q);// 队头出队列

int GetFront(Que* q);// 获取队列头部元素

int GetBack(Que* q);// 获取队列队尾元素

int Size(Que* q);// 获取队列中有效元素个数

void Destroy(Que* q);// 销毁队列

QNode* Malloc(int data)//创建节点
{
	QNode* new = (QNode*)malloc(sizeof(QNode));
	if (new == NULL)
	{
		perror("malloc false");
		return;
	}
	new->val = data;
	new->next = NULL;
    return new;
}

void Init(Que* q)// 初始化队列
{
	q->head = NULL;
	q->size = 0;
	q->tail = NULL;

}
void Push(Que* q, int data)// 队尾入队列
{
	QNode* new =Malloc(data);
	assert(new);
	if (q->head == NULL)
	{
		q->head = q->tail = new;
	}
	else
	{
		q->tail->next = new;
		q->tail = new;//指向最后一个节点
	}
	q->size++;//勿忘
}

void Pop(Que* q)// 队头出队列
{

    //删除数据之前一定要判断数据是否为空
	assert(q->head);
	QNode* next = q->head->next;
	if (q->size == 1)//只有一个有效数据时要判断,防止q->tail成为野指针
	{
		free(q->head);
		q->head = q->tail = NULL;
	}
	else
	{
		free(q->head);
		q->head = next;
	}
	q->size--;//勿忘

}

int GetFront(Que* q)// 获取队列头部元素
{
	return q->head->val;
}

int GetBack(Que* q)// 获取队列队尾元素
{
	return q->tail->val;
}

int Size(Que* q)// 获取队列中有效元素个数
{
	return q->size;
}

void Destroy(Que* q)// 销毁队列
{
	QNode* cur = q->head;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	q->head = q->tail = NULL;
	q->size = 0;
}


栈和队列的实现_第3张图片

你可能感兴趣的:(数据结构,数据结构,c语言)