数据结构1

一、什么是数据结构

    1.数据结构的起源:

        1968年,美国高德纳教授,《计算机程序设计艺术》 第一卷 《基本算法》,开创了数据结构和算法的先河

        数据结构是研究数据之间关系和操作的学科,而非计算方法

    数据结构 + 算法 = 程序      美国沃斯提出,揭示了程序的本质

    2.数据结构相关基础概念:

        数据:所有能够输入到计算机中,能够被程序处理的描述客观事物的符号

        数据项:有独立含义的数据的最小单位,也称为域;

        数据元素:组成数据的有一定含义的基本单位

        结点(节点、记录)

        数据结构:相互之间存在一种或多种特点关系的数据元素的集合

        算法:数据结构中所具备的功能、解决某种特定问题的方法

    3.数据结构的三大方面

        1.数据的逻辑关系

        2.数据的存储关系

        3.数据结构的运算

二、数据结构的逻辑和存储关系

    逻辑关系:

        集合:      数据元素同属于一个集体,但是元素之间没有任何关系

        线性结构:   数据元素之间存在一对一的关系

        树形结构:  数据元素之间存在一对多的关系

        图形结构:  数据元素之间存在多对多的关系

    存储关系:

        顺序结构:数据元素存储在连续的内存中,用数据元素的相对位置来表示关系

            优点:支持随机访问、访问,查找的效率高、适合用于频繁的查找

            缺点:对插入,删除的效率低

                 对空间的利用率低、对内存空间大小的要求高

        链式结构:数据元素存储在彼此相互独立的内存中,每个独立的元素也叫结点,每个结点增加

                 一项数据项用于存储其它相关结点的地址,以此表示结点之间的关系

            优点:插入,删除更快,更方便;空间利用率高,对内存要求不高(对比)

            缺点:查找访问效率极低,只能从头到尾逐个访问

        注意:存储结构、逻辑结构采用哪种根据实现难度,时间,空间,操作习惯等综合分析后使用

       

    逻辑结构与存储结构的关系

        线性表  顺序    链式

        树      链式    顺序

        图      顺序+链式

三、数据结构的运算

    1.创建数据结构      create(creat)

    2.销毁数据结构      destory

    3.清空数据结构      clean

    4.数据结构排序      sort

    5.插入元素          insert

    6.删除元素          delete

    7.访问元素          access

    8.查询元素          query

    9.修改元素          modify

    10.遍历数据结构     show ergodic print


 

四、线性表和链式表

    线性表

        数据项:

            存储元素的连续首地址

            表的容量

            当前元素的数量

        #define TYPE int

        tpyedef struct Array

        {

            TYPE *ptr;

            size_t cal;

            size_t cnt;

        }Array;

       

        运算:

                1.创建数据结构      create(creat)

                Array* create_array(size_t size)

                {

                    //分配顺序表结构的内存

                    Array* arr = malloc(sizeof(Array));

                    //分配存储元素的内存

                    arr->ptr = malloc(sizeof(TYPE)*size);

                    //记录表容量

                    arr->cal = size;

                    //初始化元素数量

                    arr->cnt = 0;

                    return arr;

                }

                2.销毁数据结构      destory

                3.清空数据结构      clean

                4.数据结构排序      sort

                5.插入元素          insert

                6.删除元素          delete

                7.访问元素          access

                8.查询元素          query

                9.修改元素          modify

                10.遍历数据结构     show ergodic print

        注意:1.要保持数据元素的连续性

             2.不要越界

    链表 list

        元素(结点)的数据项:

            数据域:可以放任何类型的若干个数据项

            指针域:指向下一个结点

        由若干个结点通过指针域连接到一起形成链表

        #define TYPE int

        typedef struct Node

        {

            TYPE data;

            struct List *next;

        }Node;

       

        不带头结点的单链表:

            第一个结点的数据域存储有效数据

            缺点:添加,删除结点时,可能修改指向第一个结点的指针,参数需要使用二级指针,

            才能更改指针的指向,比较麻烦。

        Node* create_node(TYPE data)

        {

            Node *node = malloc(sizeof(Node));

            node->data = data;

            node->next = NULL;

            return node;

        }

        带头结点的单链表:

            第一个结点的数据域不存储有效数据,仅仅只是使用它的指针域永远指向链表第一个有效的结点

            优点:添加,删除时会比不带头结点的链表更方便;

            注意:其他操作要从头结点的下一个结点开始;

        Node* create_node(TYPE data)

        {

            Node *node = malloc(sizeof(Node));

            node->data = data;

            node->next = NULL;

            return node;

        }

五、功能受限的表结构

    对表结构的部分功能加以限制,形成特殊的表结构

    栈:

        只有一个进出口的表结构,先进后出,FILO,

        顺序栈:

            数据域:

                存储元素的内存首地址;

                栈的容量;

                栈顶位置;

            #define TYPE int

            typedef struct ArrayList

            {

                TYPE *ptr;

                size_t cal;

                size_t top;

            }ArrayList;

           

            运算:

                创建,销毁,入栈,出栈,栈顶,栈满,栈空

            ArrayStack* create_array_stack(size_t cal)

            {

                //为栈结构分配内存

                ArrayStack* stack = malloc(sizeof(ArrayStack));

                //分配存储元素的内存

                stack->ptr = malloc(sizeof(TYPE)*cal);

                //记录栈容量

                stack->cal = cal;

                //记录栈顶位置,接下来要入栈的位置

                stack->top = 0;

                return stack;

            }

        链式栈:

            数据域:

                栈顶结点;

                结点数量;

                typedef struct Liststack

                {

                    Node *top;  //栈顶结点

                    size_t cnt; //结点数量

                } Liststack;

               

            运算:

                 创建,销毁,入栈,出栈,栈顶,栈空

                 //创建

                 Liststack *create_list_stack(void)

                 {

                     Liststack *stack = malloc(sizeof(Liststack));

                     stack->top = NULL;

                     stack->cnt = 0;

                     return stack;

                 }

        栈的应用:

            1.函数的调用,栈内存特点

            2.生产者和消费者模型(仓库 ->  栈)

            3.表达式解析

        栈的常考题:

            1.某个系列是一个栈的入栈顺序,判断哪个是正确的出栈顺序?

                可能边进边出

            2.两个顺序栈,如何能够让空间利用用最高

                让两个栈相对着入栈

            顺序栈和链式栈的区别

    队列:FIFO

        有两个端口,一个端口进,另一个端口出;先进先出

            顺序队列

                数据项:

                    存储元素的内存首地址

                    容量 cal

                    对头下标 front        //出队

                    队尾下标 tail         //入队

                typedef struct ArrayQueue

                {

                    TYPE* ptr;

                    size_t cal;

                    size_t front;       //队头

                    size_t tail;        //队尾要入队的位置

                }ArrayQueue;

                运算:

                    创建,销毁,入队,出队,队空,队满,查队头,查队尾,数量,

                //创建

                ArrayQueue* create_array_queue(size_t cal)

                {

                    ArrayQueue* queue = malloc(sizeof(ArrayQueue));

                    //多申请一个内存,解决队空

                    queue->ptr = malloc(sizeof(TYPE)*(cal+1));

                    queue->cal = cal+1;

                    queue->front = 0;

                    queue->tail = 0;

                    return queue;

                }

            注意:

                1.由一维数组+队头下标front+队尾下标tail组成;

                入队:tail++;

                出队:front++;

                为了让队列能够反复使用,我们把队列想象为一个环,当front和tail加一后

                用队列容量求余再重新赋值。

                2.如何判断队空,队满

                    1.额外多申请一个元素的内存(代价是空了一个位置,计算数量麻烦)

                    队空:front==tail

                    队满:(tail+1)%cal==front

                    计算数量:(tail-front+cal)%cal;

                    2.在队列结构设计项中增加一项数据项,用于记录队列中元素个数,

                        判断空或满时,判断该数据项就可以了。

            链式队列:

                有链表结点组成的队列结构

                数据项:

                    队头指针:

                    队尾指针:

                    结点数量:

                运算:

                    创建、销毁、队空、入队、出队、队头、队尾

           

            队列的应用:

                1.消息队列

                2.数的层序遍历

                3.图的广度优先遍历

                4.封装线程池、数据池

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值