2019独角兽企业重金招聘Python工程师标准>>>

数据结构

定义

数据结构是计算机组织,存储数据的方式。数据结构是指相互之间存在一种或多种特定关系的元素集合,大部分的数据结构的实现都需要借助C语言中的指针和结构体类型。

几种常见的数据结构

1,线性数据结构:元素之间一般存在一对一关系,是最常用的一种数据结构,比如:数组,栈,队列和线性表。

2,树形数据结构:结点间具有层次关系,每一层的结点能且只能和上一层的一个结点相关,但同时可以和下一层的多个结点相关,称为一对多关系,比如:树,堆

3,图形结构:允许多个结点之间相关,被称为多对多关系,分为有向图和多向图。

下面对这几种数据结构做简单介绍:

    数组:存放着一组相同类型的数据,需要预先指定数组的长度,有一维,二维,多维数组。

链表:是C语言中一种应用广泛的数据结构,它采用动态分配内存的方式实现,用一组任意的存储单元存放数据元素,一般为每个数据元素增加指针域,用来指向后继元素。

数组和链表的区别

从逻辑结构来看:数组必须事先定义固定的长度,不能适应数据动态的增减的情况;链表进行动态的内存分配,可以适应数据动态的增减情况,且可以方便的插入删除数据项(数组中插入删除数据项时,需要移动其他数据项)

从内存存储来看:(静态)数组从栈中分配内存(用NEW分配在堆中),对于程序员方便快捷,但自由度小;链表在堆中分配内存,自由度大但申请管理比较麻烦

从访问方式来看:数组在内存中是连续存储的,因此可以利用下标索引进行随机访问;链表是链式存储结构,在访问数据的时候只能通过线性的方式由前到后顺序访问,所以访问效率比数组低。

栈、队列、线性表:可采取顺序存储和链式存储的方法进行存储。

    顺序存储:借助数据元素在存储空间中的相对位置来表示元素之间的逻辑关系

链式存储:借助表示数据元素存储地址的指针表示元素之间的逻辑关系

:只允许在序列末端进行操作,栈的操作只能在栈顶进行,一般栈又被称为后进先出或先进后出的线性结构。

顺序栈:采用顺序存储结构的栈称为顺序栈,即需要用一片地址连续的空间来存储栈的元素,顺序栈的类型定义如下:

typedef struct{

ElemType *elem;        //存储空间的基址

int top;                        //栈顶元素的下一个元素,简称栈顶位标

int size;                       //当前分配的存储容量

int increment;              //扩容时增加的存储容量

}SqStack;

链栈:采用链式存储结构的栈称为链栈:

typedef struct LsNode{

ElemType data;            //数据域

struct LSNode *next;    //指针域

}LSNode, *LsStack;          //结点和链栈类型

链栈使用C语言的实现如下所示

/*
       The realization of the stack.
       */
        #include <stdio.h>
        #include <stdlib.h>
        #include <malloc.h>

//Define the node struct.
        typedef struct Node
        {
            int data;           //Data.
            struct Node *pNext; //Pointer the next node.
        }NODE, *PNODE;          //NODE is equivalent to Node,PNODE is equivalent to struct Node *.

//定义栈的结构体
        typedef struct Stack
        {
            PNODE pTop;         //栈顶结点
            PNODE pBottom;      //栈底结点
        }STACK, *PSTACK;

//Function declarations
        void initStack (PSTACK pStack);             //初始化栈函数
        void pushStack (PSTACK pStack, int val);    //入栈函数
        int popStack (PSTACK pStack, int *pVal);    //出栈函数
        void traverseStack (PSTACK pStack);         //遍历栈的函数
        int isEmpty (PSTACK pStack);                //判断栈是否为空的函数
        void clearStack (PSTACK pStack);            //清空栈的函数

int main (void)
        {
            STACK stack;                //定义一个栈变量
            int val;                    //用来保存出栈的内容
            initStack (&stack);         //调用初始化栈函数
            pushStack (&stack, 10); //调用入栈函数
            pushStack (&stack, 20); //调用入栈函数
            pushStack (&stack, 30); //调用入栈函数
            pushStack (&stack, 40); //调用入栈函数
            pushStack (&stack, 50); //调用入栈函数
            traverseStack (&stack); //调用遍历栈的函数
            //调用出栈的函数
            if (popStack (&stack, &val))
                printf ("出栈失败!\n");
            else
                printf ("出栈成功,出栈元素值为:%d.\n", val);
            //调用清空栈的函数
            clearStack (&stack);
            traverseStack (&stack);

return 0;
        }

void initStack (PSTACK pStack)
        {
            pStack->pTop = (PNODE)malloc(sizeof(NODE));             //创建一个空结点,让 pTOP 指向它

if (NULL != pStack->pTop)
            {
                pStack->pBottom = pStack->pTop;                     //将 pBottom 也指向空结点
                pStack->pTop->pNext = NULL;                         //清空空结点的指针欲
            }
            else                                                    //如果分配内存失败
            {
                printf ("内存分配失败,程序退出!\n");
                exit (-1);
            }

return ;
        }

void pushStack (PSTACK pStack, int val)
        {
            PNODE pNew = (PNODE)malloc (sizeof (NODE));             //动态创建一个新结点

pNew->data = val;                                       //设置新结点的数据域的值
            pNew->pNext = pStack->pTop;                             //将新结点的指针域指向之前的栈顶结点
            pStack->pTop = pNew;                                    //pTop 指向新的结点

return ;
        }

int popStack (PSTACK pStack, int *pVal)
        {
            if (isEmpty (pStack))
                return -1;
            else
            {
                //先保存栈顶元素的地址,然后将 pTop 指向下一元素,最后释放之前栈顶元素的内存
                PNODE tmpNode = pStack->pTop;
                *pVal = pStack->pTop->data;
                pStack->pTop = pStack->pTop->pNext;
                free (tmpNode);
                tmpNode = NULL;
            }

return 0;
        }

void traverseStack (PSTACK pStack)
        {
            PNODE tmpNode = pStack->pTop;                           //将栈顶赋给一个临时结点,因为在遍历栈的时候不能销毁栈

//循环遍历栈,直到栈底
            while (tmpNode != pStack->pBottom)
            {
                printf ("%d ", tmpNode->data);
                tmpNode = tmpNode->pNext;
            }

printf ("\n");

return ;
        }

int isEmpty (PSTACK pStack)
        {
            if (pStack->pTop == pStack->pBottom)
                return -1;
            else
                return 0;
        }

void clearStack (PSTACK pStack)
        {
            //栈为空则推出该函数
            if (isEmpty (pStack))
                   return ;
            else
            {
                PNODE p1 = pStack->pTop;
                PNODE p2 = NULL;
                //循环释放内存
                while (p1 != pStack->pBottom)
                {
                    p2 = p1->pNext;
                    free (p1);
                    p1 = p2;

}
                //将栈顶和栈底指向同一个指针域为空的结点
                pStack->pTop = pStack->pBottom;
            }

return ;
        }

队列:只允许在序列两端进行操作,一般队列也被称为先进先出的线性结构

循环队列:采用顺序存储结构的队列,需要按队列可能的最大长度分配存储空间,其类型定义如下:

typedef struct

{

Elemtype *base;                        //存储空间的基址

int front;                                    //队头位标

int rear;                                    //队尾位标,指示队尾元素的下一位置

int maxSize;                            //maxSize

}SqQueue;

链队列:采用链式存储结构的队列称为链队列,一般需要设置头尾指针:

typedef struct LQNode

{

Elemtype data;                                    //数据域

struct LQNode *next;                           //指针域

}LQNode, *QueuePtr;                              //结点和链栈类型

typedef struct

{

QueuePtr front;                                    //队头指针

QueuePtr rear;                                    //队尾指针

}LQueue;                                                //栈队列类型

以下为链队列的实现:

/*
   The realization of the queue.
   */
    #include <stdio.h>
    #include <stdlib.h>

typedef int ElementType;

typedef struct QNode
    {
        ElementType Element;                                //数据域
        struct QNode *pNext;                    //指向下一个元素的指针域
    }QNode, *QNodePtr;

typedef struct Node
    {
        QNodePtr front;                         //队列头
        QNodePtr rear;                          //队列尾
    }Node, *NodePtr;

ElementType isEmpty (NodePtr pNode);                            /*判断一个队列是否为空*/
    NodePtr CreateQueue (void);                                     /*创建一个队列*/
    void DisposeQueue (NodePtr pNode);                              /*销毁队列*/
    void MakeEmpty (NodePtr pNode);                                 /*清空队列*/
    void Enqueue (ElementType x, NodePtr pNode);                    /*入队*/
    ElementType Front (NodePtr pNode);                              /*若队列不为空,返回头元素数据域*/
    void Dequeue (NodePtr pNode);                                   /*若队列不为空,则删除头元素*/
    ElementType FrontAndDequeue (NodePtr pNode);                    /*返回队列中每个元素的数据域*/

ElementType isEmpty (NodePtr pNode)
    {
        return pNode->front == pNode->rear;
    }

NodePtr CreateQueue (void)
    {
        NodePtr pNode;

pNode = (NodePtr)malloc (sizeof (Node));
        pNode->front = pNode->rear = (QNodePtr)malloc (sizeof (QNode));

if (!pNode->front)
        {
            printf ("out of space! CreateQueue failed!\n");
            return NULL;
        }
        pNode->front->pNext = NULL;
        return pNode;
    }

void MakeEmpty (NodePtr pNode)
    {
        if (NULL == pNode)
        {
            printf ("Must user CreateQueue first\n");

return ;
        }
        else
            while (!isEmpty (pNode))
                Dequeue (pNode);
    }

void DisposeQueue (NodePtr pNode)
    {
        while (pNode->front)
        {
            pNode->rear = pNode->front->pNext;
            free (pNode->front);
            pNode->front = pNode->rear;
        }
        printf ("\nDispose queue completed!!!");
    }

void Enqueue (ElementType x, NodePtr pNode)
    {
        QNodePtr p = (QNodePtr)malloc (sizeof (QNode));

if (!p)
        {
            printf ("Out of space!\n");
            return ;
        }

p->Element = x;
        p->pNext = NULL;
        pNode->rear->pNext = p;
        pNode->rear=p;
    }

ElementType Front (NodePtr pNode)
    {
        if (!isEmpty (pNode))
            return pNode->front->pNext->Element;
        return 0;   /*Return value used to avoid warning*/
    }

void Dequeue (NodePtr pNode)
    {
        if (!isEmpty (pNode))
        {
            QNodePtr p = (QNodePtr)malloc (sizeof (QNode));
            if (!pNode)
            {
                printf ("Out of place!--Dequeue\n");
                return ;
            }
            p = pNode->front->pNext;
            pNode->front->pNext = p->pNext;
            if (pNode->rear == p)
                pNode->rear = pNode->front;

free (p);
        }
    }

/*
       获取队列元素中的数据元素
     */
    ElementType FrontAndDequeue (NodePtr pNode)
    {
        if (!isEmpty (pNode))
        {
            QNodePtr p = (QNodePtr)malloc (sizeof (QNode));
            if (!p)
            {
                printf ("Out of space!--FrontAndDequeue\n");
                return ;
            }
            p = pNode->front->pNext;
            ElementType temp;
            temp = p->Element;
            pNode->front->pNext = p->pNext;
            if (pNode->rear == p)
                pNode->rear = pNode->front;
            free (p);
            return temp;
        }

printf ("Empty queue!\n");

return 0;           /*Return value used to avoid warning*/
    }

int main (void)
    {
        int n, num, m;
        int i;

NodePtr pNode = CreateQueue ();
        printf ("initialization complete.\n");
        if (isEmpty(pNode))
            printf ("queue is empty!\n");
        printf ("Please input the number of elements in the queue:\n");
        scanf ("%d", &n);
        printf ("Please input %d elements put in queue:", n);
        for (i = 0; i < n; i++)
        {
            scanf ("%d", &num);
            Enqueue (num, pNode);
        }
        printf ("Front element:%d.\n", Front(pNode));
        printf ("Element is queue:");
        while (!isEmpty (pNode))
            printf ("%3d", FrontAndDequeue (pNode));

DisposeQueue (pNode);

printf ("\n");

return 0;
    }

转载于:https://my.oschina.net/xolsenberg/blog/756573

必不可少需要掌握的嵌入式知识(2) -- 经典数据结构总结之 (链表,队列)相关推荐

  1. 嵌入式工程师的经典面试题目及答案

    上个星期,去深圳一家搞ARM开发的公司面试,HR叫我做了一份卷子,里面都是C编程,心中暗喜,因为这些题基本上都在程序员面试宝典里见过.后来回到学校,在网上搜索,原来这些题都是嵌入式工程师的经典面试题目 ...

  2. 嵌入式工程师的经典面试题目

    嵌入式工程师的经典面试题目 预处理器(Preprocessor) 1 . 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)       #define  SECONDS ...

  3. 嵌入式Linux入门经典笔记

    史上最牛的Linux内核学习方法论     点击下载 我的arm_linux移植笔记     点击下载 S3C2440完全开发流程     点击下载 Linux系统命令及其使用详解完整版     点击 ...

  4. ARM+linux+2440嵌入式开发相关经典书籍(转)

    源:ARM+linux+2440嵌入式开发相关经典书籍 转载于:https://www.cnblogs.com/LittleTiger/p/7992971.html

  5. 哪些因素不会限制linux服务器并发,嵌入式技术工程师 经典面试题(含答案)

    嵌入式技术工程师 经典面试题(含答案) 来源 : 未知     2016-01-14 1.int main(){ int a;float b,c; scanf("%2d%3f%4f" ...

  6. c语言程序设计基础1千克,c语言学习知识编程经典编辑题汇总整编.doc

    c语言学习知识编程经典编辑题汇总整编.doc - C语言编程基础习题汇总1.设计一个由键盘输入三个整数,求这三个数的平均数的程序.2.编写一个程序,用于水果店售货员结账.已知苹果每斤2.50元,鸭梨每 ...

  7. 嵌入式知识概要(1)

    1.嵌入式软硬件关系图 2.嵌入式知识框图 3.C语言与数据结构

  8. 嵌入式知识-ARM裸机-学习笔记(2):利用GPIO来控制LED(附mkv210_image.c文件解析)

    嵌入式知识-ARM裸机-学习笔记(2):利用GPIO来控制LED(附mkv210_image.c文件解析) 首先声明该博客是针对朱有鹏老师的嵌入式课程进行笔记的总结. 一.通过GPIO控制点亮LED( ...

  9. 嵌入式知识-ARM裸机-学习笔记(9):SD卡启动详解(S5PV210)

    嵌入式知识-ARM裸机-学习笔记(9):SD卡启动详解(S5PV210) 一.SD卡介绍 1. SD卡背景知识和特点 SD卡.MMC卡.MicroSD.TF卡:这些卡其实内部就是Flash存储颗粒,比 ...

  10. 嵌入式Linux学习经典书籍-学完你就是高手

    很多刚入门的朋友一直都有人问我要学习资料,嵌入式实在太杂,网上很多人写的太不负责了,本书单综合了本人以及一些朋友多年的经验整理而成. 本人见识和阅读量有限,本书单可能有不对的地方,欢迎朋友指正,交流你 ...

最新文章

  1. Linux shell 学习笔记(1)— 文件和目录(查看、创建、复制、软硬链接、重命名及删除操作)
  2. 刚刚,谷歌终于回应AI专利争议:怕被碰瓷,抢先下手,永不牟利
  3. 图像的放大与缩小(2)——双线性插值放大与均值缩小
  4. 【转载】尝试使用GraphicsMagick的缩略图功能
  5. int、unsigned int、float、double 和 char 在内存中存储方式
  6. iOS开发常用的资源和资料
  7. 火狐和chrome_Firefox,Chrome和Edge都将支持WebAuthn的硬件两因素身份验证
  8. DSO(dsoframer)的接口文档
  9. concurrency runtime学习笔记之二:并行
  10. NginxWebUI - 图形化的 Nginx 配置管理工具
  11. python加密狗的制作_制作u盘加密狗
  12. 软件测试工程师需要掌握哪些技能呢?
  13. 冒险岛 PHP,php基础知识
  14. 记录贴/阴阳师core loop
  15. Sam Altman 山姆奥特曼:How To Invest In Startups如何投资初创公司
  16. BPI-M1P(全志A20)刷Android启动卡之后启动的过程
  17. 低学历可以学习IT技术吗?
  18. 蓝桥杯 拉马车 java_拉马车蓝桥杯(基于Java中的stack和queue)
  19. 西语加计算机专业怎么样,如何在电脑上添加西班牙语输入法?
  20. 水晶报表 发布 部署

热门文章

  1. access denied (java.io.FilePermission IKAnalyzer.cfg.xml read
  2. java 线程池 连接池_浅析Tomcat高并发之连接池、线程池
  3. 转载:相同版本的JVM和Java应用,在 x86 和AArch64 平台性能相差30%
  4. 某文件在桌面上,命令窗口中找不到,因为桌面是两个目录合成的
  5. LINUX终端可以使用reset清除所有输出
  6. 为什么安装了增强功能,VirtualBox菜单自动调整显示尺寸还是灰色,不能用
  7. WINDOWS NPAPI插件小结
  8. 热烈庆祝博客排名进入前一万(8448)
  9. 06_day初始化PIC
  10. 网吧电脑显示连不上服务器,Pubwin客户机连不上服务器怎么办?