C语言超详细讲解栈与队列实现实例

 更新时间:2022年03月29日 14:43:51   作者:许同学。。  
栈和队列,严格意义上来说,也属于线性表,因为它们也都用于存储逻辑关系为 "一对一" 的数据,但由于它们比较特殊,因此将其单独作为一章,做重点讲解

1.思考-1

为什么栈用数组来模拟比用链表来模拟更优一些?

队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低,时间复杂度为O(n)。

2.栈基本操作的实现

2.1 初始化栈

void StackInit(stack*ps)
{
	assert(ps);
	ps->_a = (StackDate*)malloc(sizeof(StackDate) * 4);
	ps->_top = 0;
	ps->_capacity = 4;
}

2.2 入栈

void StackPush(stack*ps, StackDate x)
{
	assert(ps);
	if (ps->_top == ps->_capacity)
	{
		stack*tmp = (StackDate*)realloc(ps, sizeof(StackDate)*(ps->_capacity) * 2);
		if (NULL == tmp)
		{
			printf("realloc failed\n");
			exit(-1);
		}
		ps = tmp;
		ps->_capacity *= 2;
	}
	ps->_a[ps->_top] = x;
	ps->_top++;
}

2.3 出栈

void StackPop(stack*ps)
{
	assert(ps);
	assert(!StackIsEmpty(ps));
	--ps->_top;
}

注意: 出栈并不是真正意义上的删除数据,而是将_top向后挪动了一个位置。

2.4 获取栈顶数据

StackDate StackTop(stack*ps)
{
	assert(ps);
	assert(!StackIsEmpty(ps));
	return ps->_a[ps->_top - 1];
}

2.5 获取栈中有效元素个数

int StackSize(stack*ps)
{
	assert(ps);
	return ps->_top;
}

2.6 判断栈是否为空

bool StackIsEmpty(stack*ps)
{
	assert(ps);
	return ps->_top == 0;
}

2.7 销毁栈

void StackDestory(stack*ps)
{
	assert(ps);
	free(ps->_a);
	ps->_a = NULL;
	ps->_top = ps->_capacity = 0;
}

3.测试

3.1 测试

void test()
{
	//插入数据
	stack  st;
	StackInit(&st);
	StackPush(&st,1);
	StackPush(&st,2);
	StackPush(&st,3);
	StackPush(&st,4);
	while (!StackIsEmpty(&st))
	{
		printf("%d ", StackTop(&st));
		StackPop(&st);
	}
	printf("\n");


	//获取栈顶数据
	StackPush(&st, 1);
	StackPush(&st, 2);
	printf("%d ", StackTop(&st));
	printf("\n");

	
	//栈中有效数据个数
	printf("%d ", StackSize(&st));

	
	//销毁栈
	StackDestory(&st);
}

3.2 测试结果

4.思考-2

为什么队列用链表模拟比数组模拟更加合适?

栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价小。

5.队列的基本操作实现

5.1 初始化队列

void QueueInit(Queue*pq)
{
	assert(pq);
	pq->_head = pq->_tail = NULL;
}

5.2 队尾入队列

void QueuePush(Queue*pq, QueueDate x)
{
	assert(pq);
	QueueNode*newnode = (QueueNode*)malloc(sizeof(QueueNode));
	if (NULL == newnode)
	{
		printf("malloc failed\n");
		exit(-1);
	}
	newnode->next = NULL;
	newnode->val = x;
	if (NULL == pq->_tail)
	{
		pq->_head = pq->_tail = newnode;
	}
	else
	{
		pq->_tail->next = newnode;
		pq->_tail = newnode;
	}
}

5.3 队头出队列

void QueuePop(Queue*pq)
{
	assert(pq);
	assert(!QueueIsEmpty(pq));
	if (NULL == pq->_head->next)
	{
		free(pq->_head);
		pq->_head = pq->_tail = NULL;
		
	}
	else
	{
		QueueNode*next = pq->_head->next;
		free(pq->_head);
		pq->_head = next;
	}
}

代码分析:

5.4 队列中有效元素的个数

int QueueSize(Queue*pq)
{
	assert(pq);
	int count = 0;
	QueueNode*cur = pq->_head;
	while (cur)
	{
		++count;
		cur = cur->next;
	}
	return count;
}

5.5 判断队列是否为空

bool QueueIsEmpty(Queue*pq)
{
	assert(pq);
	return pq->_head == NULL;
}

5.6 获取队头数据

QueueDate QueueFront(Queue*pq)
{
	assert(pq);
	assert(!QueueIsEmpty(pq));
	return pq->_head->val;
}

5.7 获取队尾的数据

QueueDate QueueBack(Queue*pq)
{
	assert(pq);
	assert(!QueueIsEmpty(pq));
	return pq->_tail->val;
}

5.8 销毁队列

void QueueDestory(Queue*pq)
{
	assert(pq);
	while (pq->_head)
	{
		if (pq->_head == pq->_tail)
		{
			free(pq->_head);
			pq->_head = pq->_tail = NULL;
		}
		else
		{
			QueueNode*next = pq->_head->next;
			free(pq->_head);
			pq->_head = next;
		}
	}
}

注意: 和队头出队列一样分析。

6.测试

6.1 测试

void test1()
{
	//插入数据
	Queue q;
	QueueInit(&q);
	QueuePush(&q, 1);
	QueuePush(&q, 2);
	QueuePush(&q, 3);
	QueuePush(&q, 4);


	//有效数据的个数
	printf("%d ", QueueSize(&q));
	printf("\n");


	//获取队头数据
	printf("%d",QueueFront(&q));
	printf("\n");


	//获取队尾数据
	printf("%d",QueueBack(&q));
	printf("\n");


	//出队
	QueuePop(&q);
	while (!QueueIsEmpty(&q))
	{
		printf("%d ", QueueFront(&q));
		QueuePop(&q);
	}
	printf("\n");


	//销毁
	QueueDestory(&q);
	printf("\n");
}

6.2 测试结果

今天数据结构栈与队列的相关知识点就分享到这里了,感谢你的浏览,如果对你有帮助的话,可以给个关注,顺便来个赞。

到此这篇关于C语言超详细讲解栈与队列实现实例的文章就介绍到这了,更多相关C语言 栈与队列内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 适合初学者的C语言数据类型的讲解

    适合初学者的C语言数据类型的讲解

    在 C 语言中,数据类型指的是用于声明不同类型的变量或函数的一个广泛的系统。变量的类型决定了变量存储占用的空间,以及如何解释存储的位模式。
    2022-04-04
  • 详解C++编程中的变量相关知识

    详解C++编程中的变量相关知识

    这篇文章主要介绍了详解C++编程中的变量相关知识,是C++入门学习中的基础知识,需要的朋友可以参考下
    2015-09-09
  • 浅析C语言中typeof关键字用法

    浅析C语言中typeof关键字用法

    typeof关键字是C语言中的一个新扩展。在linux内核源代码中广泛使用。接下来通过本文给大家分享C语言中typeof关键字用法,需要的朋友参考下
    2017-02-02
  • C语言删除输入字符串中的空格示例代码

    C语言删除输入字符串中的空格示例代码

    最近工作中遇到了需求,要删除字符串中的所有空格,就要筛选出空格字符,这篇文章主要给大家介绍了关于利用C语言删除输入字符串中的空格的相关资料,需要的朋友可以参考下
    2022-12-12
  • c++中创建.in文件的方法步骤

    c++中创建.in文件的方法步骤

    在本篇文章里小编给大家分享了一篇关于c++中创建.in文件的方法步骤的内容以及相关知识点,需要的朋友们学习下。
    2019-07-07
  • C语言打印华氏-摄氏温度对照表的方法

    C语言打印华氏-摄氏温度对照表的方法

    这篇文章主要介绍了C语言打印华氏-摄氏温度对照表的方法,涉及C语言字符串与数字操作的相关技巧,非常简单实用,需要的朋友可以参考下
    2015-07-07
  • C++11 移动构造函数的使用

    C++11 移动构造函数的使用

    本文主要介绍了C++11 移动构造函数的使用,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • C++ 利用硬件加速矩阵乘法的实现

    C++ 利用硬件加速矩阵乘法的实现

    这篇文章主要介绍了C++ 利用硬件加速矩阵乘法的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • C++反射的一种实现方法详解

    C++反射的一种实现方法详解

    这篇文章主要给大家介绍了关于C++反射的一种实现方法,文中通过示例代码介绍的非常详细,对大家学习或者使用C++具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-06-06
  • VSCode插件开发全攻略之package.json详解

    VSCode插件开发全攻略之package.json详解

    这篇文章主要介绍了VSCode插件开发全攻略之package.json的相关知识,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-05-05

最新评论