【数据结构】栈和队列

2023-11-01

一,栈

1,栈的简单介绍

栈是一种特殊的线性表,只允许在线性表的一段插入或删除数据,这一段成为栈顶,另一端称为栈底。所以,栈具有后入先出的性质(last in first out)。
由于,用链表和顺序表的性能相差不大,下面我们用顺序表来实现。

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

typedef int STDateType;
typedef struct Stack
{
	STDateType* a;
	int capcity;
	int top;
}Stack;

//初始化
void StackInit(Stack* ps);
//销毁
void StackDestroy(Stack* ps);
//压栈
void StackPush(Stack* ps, STDateType x);
//弹栈
void StackPop(Stack* ps);
//取栈顶
STDateType StackTop(Stack* ps);
//判空
bool StackEmpty(Stack* ps);
//栈的大小
int StackSize(Stack* ps);

2,栈的相关函数接口实现

(1)初始化

void StackInit(Stack* ps)
{
	assert(ps);
	ps->a = (STDateType*)malloc(sizeof(STDateType) * 4);
	if (!ps->a)
	{
		perror("malloc fail");
		exit(-1);
	}
	ps->capcity = 4;
	ps->top = -1;
}

top为栈顶元素的下标。

(2)销毁

void StackDestroy(Stack* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->capcity = 0;
	ps->top = -1;
}

(3)压栈

void StackPush(Stack* ps, STDateType x)
{
	assert(ps);
	if (ps->top + 1 == ps->capcity)
	{
		STDateType* tmp = (STDateType*)realloc(ps->a,sizeof(STDateType) * ps->capcity * 2);
		if (!tmp)
		{
			perror("realloc fail");
			exit(-1);
		}
		ps->a = tmp;
		ps->capcity *= 2;
	}
	ps->top++;
	ps->a[ps->top] = x;
}

注意: 顺序表实现栈的时候,压栈前首先检验空间是否充足。

(4)弹栈

void StackPop(Stack* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	ps->top--;
}

注意: 弹栈前,要注意是否为空栈。

(5)判空

bool StackEmpty(Stack* ps)
{
	assert(ps);
	return ps->top == -1;
}

(6)取栈顶元素

STDateType StackTop(Stack* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	return ps->a[ps->top];
}

注意: 取栈顶元素前,先判断栈是否为空栈。

(7)栈的大小

int StackSize(Stack* ps)
{
	assert(ps);
	return ps->top + 1;
}

二,队列

1,队列的简单介绍

队列也是特殊的线性表,只允许在队头删除数据,在队尾插入数据。
因此,队列具有先进先出的性质(first in first out)。

由于,使用顺序表实现队列时,我们在删除队头数据时需要大量移动数据,性能较低,所以我们采用链表实现队列。

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

typedef int QDateType;
typedef struct QueueNode
{
	QDateType data;
	struct QueueNode* next;
}QNode;

typedef struct Queue
{
	QNode* front;
	QNode* rear;
	int size;
}Queue;

//初始化
void QueueInit(Queue* pq);
//销毁
void QueueDestroy(Queue* pq);
//插入
void QueuePush(Queue* pq, QDateType x);
//删除
void QueuePop(Queue* pq);
//判空
bool QueueEmpty(Queue* pq);
//队列大小
int QueueSize(Queue* pq);
//取队头
QDateType QueueFront(Queue* pq);
//取队尾
QDateType QueueBack(Queue* pq);

2,队列的相关函数接口实现

(1)初始化

void QueueInit(Queue* pq)
{
	assert(pq);
	pq->front = NULL;
	pq->rear = NULL;
	pq->size = 0;
}

(2)销毁

void QueueDestroy(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->front;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->front = NULL;
	pq->rear = NULL;
	pq->size = 0;
}

(3)插入

void QueuePush(Queue* pq, QDateType x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (!newnode)
	{
		perror("malloc fail");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;
	if (pq->rear == NULL)
	{
		pq->front = newnode;
		pq->rear = newnode;
	}
	else
	{
		pq->rear->next = newnode;
		pq->rear = newnode;
	}
	pq->size++;
}

(4)删除

void QueuePop(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	if (pq->front->next == NULL)
	{
		free(pq->front);
		pq->front = NULL;
		pq->rear = NULL;
	}
	else
	{
		QNode* next = pq->front->next;
		free(pq->front);
		pq->front = next;
	}
	pq->size--;
}

注意: 删数据前应先判断队列是否为空。

(5)判空

bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->front == NULL && pq->rear == NULL;
}

(6)大小

int QueueSize(Queue* pq)
{
	assert(pq);
	return pq->size;
}

(7)取队头数据

QDateType QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->front->data;
}

注意: 取数据前应先判断队列是否为空。

(8)取队尾数据

QDateType QueueBack(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->rear->data;
}

三,栈与队列的应用

1,括号匹配

在这里插入图片描述
这个例子就很适合用栈这种数据结构来解决,非常符号后进先出的特点。
分析: 遇到左括号我们就压栈,遇到右括号我们就取栈顶元素与之匹配,若匹配成功就继续,知道栈为空并且字符串遍历到’\0’,就证明匹配成功。
匹配不成功的场景有三种,应注意:
1,右括号多于左括号
2,左括号多于右括号
3,当前右括号与栈顶的左括号不匹配
下面看代码:

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

typedef int STDateType;
typedef struct Stack
{
	STDateType* a;
	int capcity;
	int top;
}Stack;

//初始化
void StackInit(Stack* ps);
//销毁
void StackDestroy(Stack* ps);
//压栈
void StackPush(Stack* ps, STDateType x);
//弹栈
void StackPop(Stack* ps);
//取栈顶
STDateType StackTop(Stack* ps);
//判空
bool StackEmpty(Stack* ps);
//栈的大小
int StackSize(Stack* ps);

void StackInit(Stack* ps)
{
	assert(ps);
	ps->a = (STDateType*)malloc(sizeof(STDateType) * 4);
	if (!ps->a)
	{
		perror("malloc fail");
		exit(-1);
	}
	ps->capcity = 4;
	ps->top = -1;
}
void StackDestroy(Stack* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->capcity = 0;
	ps->top = -1;
}
void StackPush(Stack* ps, STDateType x)
{
	assert(ps);
	if (ps->top + 1 == ps->capcity)
	{
		STDateType* tmp = (STDateType*)realloc(ps->a,sizeof(STDateType) * ps->capcity * 2);
		if (!tmp)
		{
			perror("realloc fail");
			exit(-1);
		}
		ps->a = tmp;
		ps->capcity *= 2;
	}
	ps->top++;
	ps->a[ps->top] = x;
}
void StackPop(Stack* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	ps->top--;
}
STDateType StackTop(Stack* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	return ps->a[ps->top];
}
bool StackEmpty(Stack* ps)
{
	assert(ps);
	return ps->top == -1;
}
int StackSize(Stack* ps)
{
	assert(ps);
	return ps->top + 1;
}


bool isValid(char * s){
    Stack st;
    StackInit(&st);
    //开始遍历字符串,左括号进栈,右括号与栈顶匹配
    while(*s)
    {
        if(*s=='{'||*s=='('||*s=='[')
        {
            StackPush(&st,*s);
            s++;
        }
        else
        {
            if(StackEmpty(&st))
            {
                StackDestroy(&st);
                return false;
            }
            char tmp=StackTop(&st);
            StackPop(&st);
            if((*s==')'&&tmp!='(')||
            (*s==']'&&tmp!='[')||
            (*s=='}'&&tmp!='{'))
            {
                StackDestroy(&st);
                return false;
            }
            s++;
        }
    }
    if(StackEmpty(&st))
    {
        StackDestroy(&st);
        return true;
    }
    StackDestroy(&st);
    return false;

}

2,栈实现队列

在这里插入图片描述

分析: 由于从一个栈的数据导入到另一个栈中,会有使数据倒置的性质。
在这里插入图片描述
在这里插入图片描述

所以,我们就用一个push栈和一个pop栈来实现,其中插入数据都进入到push栈中,pop数据都从pop栈中,其中如果pop栈为空的话,我们就把push栈中的数据导入到pop栈当中。
下面看代码:

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

typedef int STDateType;
typedef struct Stack
{
	STDateType* a;
	int capcity;
	int top;
}Stack;

//初始化
void StackInit(Stack* ps);
//销毁
void StackDestroy(Stack* ps);
//压栈
void StackPush(Stack* ps, STDateType x);
//弹栈
void StackPop(Stack* ps);
//取栈顶
STDateType StackTop(Stack* ps);
//判空
bool StackEmpty(Stack* ps);
//栈的大小
int StackSize(Stack* ps);

void StackInit(Stack* ps)
{
	assert(ps);
	ps->a = (STDateType*)malloc(sizeof(STDateType) * 4);
	if (!ps->a)
	{
		perror("malloc fail");
		exit(-1);
	}
	ps->capcity = 4;
	ps->top = -1;
}
void StackDestroy(Stack* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->capcity = 0;
	ps->top = -1;
}
void StackPush(Stack* ps, STDateType x)
{
	assert(ps);
	if (ps->top + 1 == ps->capcity)
	{
		STDateType* tmp = (STDateType*)realloc(ps->a,sizeof(STDateType) * ps->capcity * 2);
		if (!tmp)
		{
			perror("realloc fail");
			exit(-1);
		}
		ps->a = tmp;
		ps->capcity *= 2;
	}
	ps->top++;
	ps->a[ps->top] = x;
}
void StackPop(Stack* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	ps->top--;
}
STDateType StackTop(Stack* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	return ps->a[ps->top];
}
bool StackEmpty(Stack* ps)
{
	assert(ps);
	return ps->top == -1;
}
int StackSize(Stack* ps)
{
	assert(ps);
	return ps->top + 1;
}

typedef struct {
    Stack pushst;
    Stack popst;
} MyQueue;


MyQueue* myQueueCreate() {
    MyQueue* tmp=(MyQueue*)malloc(sizeof(MyQueue));
    StackInit(&tmp->pushst);
    StackInit(&tmp->popst);
    return tmp;
}

void myQueuePush(MyQueue* obj, int x) {
    StackPush(&obj->pushst,x);
}

int myQueuePop(MyQueue* obj) {
    if(StackEmpty(&obj->popst))
    {
        while(!StackEmpty(&obj->pushst))
        {
            StackPush(&obj->popst,StackTop(&obj->pushst));
            StackPop(&obj->pushst);
        }
    }
    int ret=StackTop(&obj->popst);
    StackPop(&obj->popst);
    return ret;
}

int myQueuePeek(MyQueue* obj) {
    if(StackEmpty(&obj->popst))
    {
        while(!StackEmpty(&obj->pushst))
        {
            StackPush(&obj->popst,StackTop(&obj->pushst));
            StackPop(&obj->pushst);
        }
    }
    int ret=StackTop(&obj->popst);
    return ret;
}

bool myQueueEmpty(MyQueue* obj) {
    return StackEmpty(&obj->pushst)&&StackEmpty(&obj->popst);
}

void myQueueFree(MyQueue* obj) {
    StackEmpty(&obj->pushst);
    StackEmpty(&obj->popst);
    free(obj);
}

3,队列实现栈

在这里插入图片描述
分析: 队列的性质是先进先出,要想pop出栈顶元素,那么我们可以将有数据的队列中的数据挪到另一个队列中,只剩一个数据,然后弹出。
例如:进栈的顺序为 1 2 3 4 的一组数据
我们要pop出栈顶数据,那么
在这里插入图片描述
在这里插入图片描述
将4弹出即可。
但是在入栈的时候要注意,要将数据压入到有数据的一个队列中。
下面看代码:

typedef int QDataType;
typedef struct QueueNode
{
	QDataType data;
	struct QueueNode* next;
}QNode;

typedef struct Queue
{
	QNode* front;
	QNode* back;
	int len;
}Queue;

void QueueInit(Queue* pq);
void QueueDestroy(Queue* pq);
void QueuePush(Queue* pq, QDataType x);
void QueuePop(Queue* pq);
bool QueueEmpty(Queue* pq);
int QueueSize(Queue* pq);
QDataType QueueFront(Queue* pq);
QDataType QueueBack(Queue* pq);
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->back = NULL;
	pq->front = NULL;
	pq->len = 0;
}
void QueueDestroy(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->front;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->back = pq->front = NULL;
	pq->len = 0;
}
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (!newnode)
	{
		perror("malloc fail");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;
	if (pq->back == NULL)
	{
		pq->front = pq->back = newnode;
	}
	else
	{
		pq->back->next = newnode;
		pq->back = newnode;
	}
	pq->len++;
}
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	if (pq->front->next == NULL)
	{
		free(pq->front);
		pq->back = pq->front = NULL;
	}
	else
	{
		QNode* next = pq->front->next;
		free(pq->front);
		pq->front = next;
	}
	pq->len--;
}
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->back == NULL && pq->front == NULL;
}
int QueueSize(Queue* pq)
{
	assert(pq);
	return pq->len;
}
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->front->data;
}
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->back->data;
}

typedef struct {
    Queue q1;
    Queue q2;
} MyStack;


MyStack* myStackCreate() {
    MyStack* tmp=(MyStack*)malloc(sizeof(MyStack));
    QueueInit(&tmp->q1);
    QueueInit(&tmp->q2);
    return tmp;
}

void myStackPush(MyStack* obj, int x) {
    if(!QueueEmpty(&obj->q1))
    {
        QueuePush(&obj->q1,x);
    }
    else
    {
        QueuePush(&obj->q2,x);
    }
}

int myStackPop(MyStack* obj) {
    QNode* emptyQ=&obj->q1;
    QNode* nonemptyQ=&obj->q2;
    if(!QueueEmpty(&obj->q1))
    {
        nonemptyQ=&obj->q1;
        emptyQ=&obj->q2;
    }
    //将非空的队列数据移动到空的队列中,就剩最后一个数据
    while(QueueSize(nonemptyQ)>1)
    {
        QueuePush(emptyQ,QueueFront(nonemptyQ));
        QueuePop(nonemptyQ);
    }
    int ret=QueueFront(nonemptyQ);
    QueuePop(nonemptyQ);
    return ret;
}

int myStackTop(MyStack* obj) {
    QNode* emptyQ=&obj->q1;
    QNode* nonemptyQ=&obj->q2;
    if(!QueueEmpty(&obj->q1))
    {
        nonemptyQ=&obj->q1;
        emptyQ=&obj->q2;
    }
    return QueueBack(nonemptyQ);
}

bool myStackEmpty(MyStack* obj) {
    return QueueEmpty(&obj->q1)&&QueueEmpty(&obj->q2);
}

void myStackFree(MyStack* obj) {
    QueueDestroy(&obj->q1);
    QueueDestroy(&obj->q2);
    free(obj);
}

4,环形队列

在这里插入图片描述
分析: 如果使用单项循环链表来实现循环队列的话:
当front指针与rear指针相等时,就是队列为空的时候。所以rear指针就指向了最后一个结点的下一个结点,这样我们在获取队尾数据时就会很不方便。

所以,我们采用顺序表来实现循环队列:
顺序表的优势就在于支持下标的随机访问,我们在pop数据时,front指针也会随之变化,这样就不会出现假溢出现象。
应注意的是,顺序表如何实现循环呢?
这个好解决,无论front好事rear指针走到顺序表尾的时候,再运动的时候,就需要(front+1)%(顺序表长度)达到循环的效果。
还有一个问题就是当队列满的时候也是rear等于front,所以我们就少使用一个位置,
当front领先rear并且,他们中间空了一个结点时就为满
如图:
在这里插入图片描述

typedef struct {
    int* a;
    int front;
    int rear;
    int k;
} MyCircularQueue;


MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue* tmp=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    tmp->a=(int*)malloc(sizeof(int)*(k+1));
    tmp->front=tmp->rear=0;
    tmp->k=k;
    return tmp;
}

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    return obj->front==obj->rear;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) {
    return (obj->rear+1)%(obj->k+1)==obj->front;
}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    if(myCircularQueueIsFull(obj))
    {
        return false;
    }
    obj->a[obj->rear]=value;
    obj->rear=(obj->rear+1)%(obj->k+1);
    return true;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
    {
        return false;
    }
    obj->front=(obj->front+1)%(obj->k+1);
    return true;
}

int myCircularQueueFront(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
    return obj->a[obj->front];
}

int myCircularQueueRear(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
    return obj->a[(obj->rear+obj->k)%(obj->k+1)];
}

void myCircularQueueFree(MyCircularQueue* obj) {
    free(obj->a);
    free(obj);
}

谢谢观看,欢迎指正。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【数据结构】栈和队列 的相关文章

  • 如何实现百万并发连接的 Nginx 集群

    要实现百万并发连接的 Nginx 集群 可以考虑以下几种方案 横向扩展 使用多台 Nginx 服务器来处理并发连接 通过将流量分发到多个节点 每个节点处理一部分连接 从而实现并发连接的处理能力扩展 可以使用负载均衡器 如硬件负载均衡器 Ng

随机推荐

  • Anaconda安装教程(超详细)

    Anaconda安装教程 超详细 2022 11 16成功配置写下这篇文章 1 Anaconda的下载 我是在官网下载的 并没有网上说的那么慢 大概5 7分钟左右就下好了 这里附上官网下载地址 Anaconda官网下载地址 进去是这样的 直
  • alibaba/COLA 4.0框架 使用记录

    文章目录 背景 COLA框架 开发情况 出现的问题 总结 建议 背景 简介 开发团队之前没用过DDD开发 第一次用https github com alibaba COLA框架试着做项目 记录一些遇到的问题 https github com
  • 红黑树与平衡二叉树区别?

    如果说平衡二叉树是一个类的话 那么红黑树就是该类的一个实例 算法的书我丢久了 一下子也找不到 我是凭记忆说的 红黑树的算法比较麻烦 但它的思想很好 如果理解了它的思想也就理解它的算法 我也只记得思想 具体算法记不得了 我就在这说说思想吧 红
  • html5 图片 遮罩层,6种炫酷的鼠标滑过图片显示遮罩层特效

    这是一款使用jQuery和CSS3制作的炫酷的鼠标滑过图片显示遮罩层特效 该图片制作层特效共6种不同的效果 使用一些简单的jQuery代码和CSS3过渡效果来完成 简单实用 可以为网站图片添加非常不错的效果 制作方法 HTML结构 该图片遮
  • 亿图脑图MindMaster(Pro)

    下载地址 https www edrawsoft cn download 微信扫码登录 无限结点
  • QT交叉编译arm

    QT环境以及交叉编译环境的搭建 提示 这个操作比较常规 我就说一下自己遇到的一些问题然后一些注意事项 文章目录 QT环境以及交叉编译环境的搭建 前言 一 QT使用方面 先得知道QT是怎么回事 QT是什么和我认为的优势 干货来了 qmake
  • 虚拟地址 到底如何映射到 物理地址 的?

    一 背景 1 讲故事 我发现有很多的 NET程序员 写了很多年的代码都没弄清楚什么是 虚拟地址 更不用谈什么是 物理地址 以及Windows是如何实现地址映射的了 这一篇我们就来聊一聊这两者之间的联系 二 地址映射研究 1 找虚拟地址 怎么
  • html调用内网海康威视摄像头

    html调用内网海康威视摄像头 我的需求很简单就是在html的主页上用iframe加载出摄像头 海康威视的摄像头无法直接调用 必须安装海康提供的web插件包 使用插件的demo是可以调用的 但是单独搞出来又无法使用 所以直接在原来的demo
  • opencv ffmpeg推流

    基于opencv采集推流 1 opencv采集rtsp解码 可以基于usb 摄像机 调用系统驱动 和rtsp 调用ffmpeg 接口 转yuv加解码 摄像机 2 ffmpeg缩放转换像素格式 3 ffmpeg编码H264 4 ffmpeg推
  • 使用JS实现对页面的繁体简体翻译转换

    使用JS实现对页面的繁体简体翻译转换 效果图 一 HTML代码 二 Js代码 总结 效果图 废话少说直接上代码 一 HTML代码
  • wsl无法连接到win上的docker

    https docs docker com desktop windows wsl
  • QT 写一个属于自己的消息弹窗MessageBox

    前言 在接触公司的一个桌面应用项目后 发现里面很多窗体都是自己写的而不是使用QT自带的 例如消息弹窗 今天这篇博客就记录下来如何自己写一个消息弹窗 内容可能有点多 但都是本人自己一步一步操作后 测试可行后才记录下博客这里来的 希望对看到这篇
  • kaldi中SHELL调用C++程序过程源码分析

    引入 kaldi真正的核心源码 都是C 写成的 这个结论可以从如下两点得以确认 1 在kaldi的源码kaldi src目录下 能看到很多扩展名为 cc的源程序 这是linux下C 源码 2 在源码中 比如kaldi src featbin
  • 和导师的第二次探讨

    Jason提问 导师 最近读文献的方面我碰到两个问题 一 就是感觉读的太杂了 人工智能方向太大 文章五花八门 二 内容刚接触感觉晦涩难懂 特别是英文文献 而且用翻译软件意思有时候翻译成中文就感觉也不对 我应该如何解决呢 导师回答 对于问题一
  • sourceInsight官网介绍及插入定制语言支持

    sourceInsight官网介绍及插入定制语言支持 版本说明 版本 作者 日期 备注 0 1 ZY 2019 6 4 初稿 目录 文章目录 sourceInsight官网介绍及插入定制语言支持 版本说明 目录 一 sourceinsigh
  • 已经有了ERP,为什么还要上MES?

    当前 制造企业面临着巨大的竞争和成本压力 利润越来越少 交货时间要求越来越短 人力成本越来越高 产品越来越复杂 大多数企业已经在使用ERP系统了 他们会想 我已经上了ERP了 为什么还需要MES系统 许多工厂车间只有很有限的IT系统 比如自
  • Vector简介说明

    转自 Vector简介说明 下文笔者讲述Vector简介说明 如下所示 Vector简介 Vector集合和ArrayList集合功能相似 底层都是通过数组来实现集合的 Vector和ArrayList最大的区别是Vector的很多方法都是
  • 开发Android硬件访问服务

    在http blog csdn net getnextwindow article details 47731597中 为Android系统添加了HAL模块 开发好一个硬件抽象层以后 我们通常还需要在应用程序框架中实现一个硬件访问服务 硬件
  • 数据结构实验--带环、相交链表问题

    一 问题描述 基于课程上机关于单链表的作业 要求进一步实现以下需求 1 构造链表后 将元素值为 m 和 n 从键盘输入 如有多个相同元素值 仅考虑首个出现的元素 的节点建立连接 注意判断节点出现的先后关系 将后面出现的节点 假设为 n 的链
  • 【数据结构】栈和队列

    栈和队列 一 栈 1 栈的简单介绍 2 栈的相关函数接口实现 1 初始化 2 销毁 3 压栈 4 弹栈 5 判空 6 取栈顶元素 7 栈的大小 二 队列 1 队列的简单介绍 2 队列的相关函数接口实现 1 初始化 2 销毁 3 插入 4 删