数据结构学习——栈与队列的C语言实现

前言

也是数据结构的学习。栈和队列很相似,所以我就用C语言一起实现它们(毕竟不会c++),毕竟写完一个就可以说另一个也基本上写完了。当然我说的学习是理解,关于代码的参考修正与美化,都是在网上找的。

关于实现栈与队列

栈和队列都是用带表头的单链表实现的,因为也没学过单链表,所以在实现栈与队列之前去学了下单链表,可以说现在学了一半的栈,一半的队列,一般的链表。

栈——先进后出

Push

用结构体开一个链表表头,表头不存数据,目前表头里的指针指向NULL:

Head_Stack
数据-
指向的栈Stack_1

入栈就是把栈插进表头的后面,并读入栈所要储存的数据(假定为1):

Head_StackStack_1
数据-1
指向的栈Stack_1NULL

假设新栈为Stack_New,要存储数字3:

New_Stack
数据3

插入的结果就是:

Head_StackNew_StackStack_1
数据-31
指向的栈New_StackStack_1NULL

以此类推即可让栈一堆再堆

GetTop

每次要提取的栈即最顶上的栈,肯定就是Head_Stack所指向的栈,所以只要栈不空,返回所存储的值即可。

Pop

跟GetTop里说的一样,先把该栈之后的栈和Head_Stack连接,再弹出该栈即可。

关于其它函数

  • InitStack:创建栈
  • ClearStack:把栈清空
  • DestroyStack:把栈消灭
  • StackEmpty:检测栈是否为空
  • StackLength:检测栈目前的长度

代码实现

用一个stack.h的自制头文件装起来,方便以后使用。

#ifndef __STACK_H__
#define __STACK_H__

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

//创建链表,定义元素类型
typedef int TypeData;
typedef struct node {
	TypeData data;
	struct node* next;
}Stack;

//判断栈是否为空,为空返回1,不为空返回0
int StackEmpty(Stack* stack)
{
	return stack->next == NULL;
}

//创建栈,成功返回栈,失败返回NULL
Stack* InitStack()
{
	Stack* H_stack = (Stack*)malloc(sizeof(Stack));
	if (H_stack != NULL)
	{
		H_stack->next = NULL;
		return H_stack;
	}
	return NULL;
}

//弹出栈,成功返回1,失败返回0
int Pop(Stack* stack)
{
	if (!StackEmpty(stack))
	{
		Stack* temp_stack = stack->next;
		stack->next = temp_stack->next;
		free(temp_stack);
		return 1;
	}
	return 0;
}

//提取栈,成功返回data的值,失败返回-1
TypeData GetTop(Stack* stack)
{
	if (!StackEmpty(stack))
	{
		return stack->next->data;
	}
	return EOF;
}

//放入栈,成功返回,失败返回0
int Push(Stack* stack, TypeData data)
{
	Stack* new_stack = (Stack*)malloc(sizeof(Stack));
	if (new_stack != NULL)
	{
		new_stack->data = data;
		new_stack->next = stack->next;
		stack->next = new_stack;
		return 1;
	}
	return 0;
}

//清空栈,如果已经是空栈则返回1,不然返回0
int ClearStack(Stack* stack)
{
	while (!StackEmpty(stack))
	{
		Pop(stack);
	}
	if (StackEmpty(stack))
	{
		return 1;
	}
	return 0;
}

//我觉得破坏栈之前还是先把栈清空要好一点,破坏成功返回1,否则返回0
int DestroyStack(Stack* stack)
{
	if (ClearStack(stack))
	{
		free(stack);
		return 1;
	}
	return 0;
}

//顺藤摸瓜法求计算栈目前的长度(元素数目),最后返回n,没有栈则返回0
int StackLength(Stack* stack)
{
		int n;
		Stack* test_stack;
		for (n = 0, test_stack = stack; test_stack->next != NULL; test_stack = test_stack->next, n++);
		return n;
}

#endif

以上就是关于栈的内容。

队列——先进先出

与栈的不同

队列与栈很相似,只不过插入元素时并非在队头之后插入,而是在队列的末尾插入。队列里的都是文明人,如果说栈也是队列的话,那就是只会插队的莽夫。

名称上的不同

数据类型队列
插入PushEnQueue
弹出PopDeQueue
提取GetTopGetHead
创建InitStackInitQueue
清空ClearStackClearQueue
销毁DestroyStackDestroyQueue
计算长度StackLengthQueueLength
判断是否为空StackEmptyQueueEmpty

所作修改

为了实现在队尾插入元素,还需要一个指针来指向队尾。
我把结构体的next换成了front与back,front指向前一个元素,back指向后一个元素,而队头的front指向队尾元素,队尾元素的back为NULL。

代码实现

还是用一个queue.h存起来

#ifndef __QUEUE_H__
#define __QUEUE_H__

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef int TypeData;
typedef struct node {
    TypeData data;
    struct node* front;
    struct node* back;
}Queue;

int QueueEmpty(Queue* queue)
{
    return queue->back == NULL;
}

Queue* InitQueue()
{
    Queue* head_queue = (Queue*)malloc(sizeof(Queue));
    if (head_queue != NULL)
    {
        head_queue->back = NULL;
        head_queue->front = head_queue;
        return head_queue;
    }
    return NULL;
}

int DeQueue(Queue* queue)
{
    if (!QueueEmpty(queue))
    {
        Queue* temp_queue = queue->back;
        queue->back = temp_queue->back;
        free(temp_queue);
        return 1;
    }
    return 0;
}

TypeData GetHead(Queue* queue)
{
    if (!QueueEmpty(queue))
    {
        return queue->back->data;
    }
    return EOF;
}

int EnQueue(Queue* queue, TypeData data)
{
    Queue* new_queue = (Queue*)malloc(sizeof(Queue));
    if (new_queue != NULL)
    {
        new_queue->data = data;
        new_queue->front = queue->front;
        new_queue->back = queue->front->back;
        queue->front->back = new_queue;
        queue->front = new_queue;
        return 1;
    }
    return 0;
}

int ClearQueue(Queue* queue)
{
    while (!QueueEmpty(queue))
    {
        DeQueue(queue);
    }
    if (QueueEmpty(queue))
    {
        return 1;
    }
    return 0;
}

int DestroyQueue(Queue* queue)
{
    if (ClearQueue(queue))
    {
        free(queue);
        return 1;
    }
    return 0;
}

int QueueLength(Queue* queue)
{
    int n;
    Queue* test_queue;
    for (n = 0, test_queue = queue; test_queue->back != NULL; test_queue = test_queue->back, n++);
    return n;
}

#endif

我的想法

队列我既然加了个front的指针,那么理应可以实现循环队列,优先队列,双向队列之类的东西,但是,再说再说orz…

以上就是关于队列的内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值