数据结构顺序表和链式表

数据结构

一、什么是数据结构

   1.数据结构的起源

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

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

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

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

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

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

     数据元素:组成数据的有一定含义的基本单位,也成为结点、节点、记录

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

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

   3.数据结构的三个方面

        数据的逻辑关系

        数据的存储关系

        数据结构的运算

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

    1.逻辑关系:

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

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

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

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

    2.存储(物理)关系:

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

    优点:支持随机访问、访问查找效率极高、适合查找数据频繁的结构

    缺点:插入、删除时效率低、不方便,内存空间利用率低、要求高

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

    项用于存储其他相关节点的地址,以此表示结点之间的关系

    优点:插入、删除更方便,空间利用率极高、对内存要求不高

    缺点:不支持随机访问、只能从头到尾逐个访问

注意:逻辑结构和存储结构采用哪种根据实现难度、空间时间要求、操作习惯等方面综合考虑选择合适的结构

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

    线性表  顺序  链式

    树      链式  顺序

    图      顺序+链式

三、数据结构的运算

    1.创建数据结构      create creat

    2.销毁数据结构      destroy

    3.清空数据结构      clean

    4.数据结构排序      sort

    5.插入元素          insert

    6.删除元素          delete

    7.访问元素          access

    8.查询元素          query

    9.修改元素          modify

    10.遍历数据结构     ergodic show print

四、顺序表和链式表实现

    顺序表

        数据项:

            存储元素的连续内存首地址

            表的容量

            当前元素的数量

        运算:

            创建、销毁、清空、插入、删除、访问、查询、修改、排序、遍历

        注意:

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

            2.不要越界 

   //设计顺序表结构

   

    #include <stdio.h>

    #define TYPE int

    #include <stdbool.h>

    #include <stdlib.h>

    #include <string.h>

    typedef struct Array

    {

        TYPE* prt;      //存储元素的内存首地址

        size_t cal;     //表的容量

        size_t cnt;     //已存储元素的数量

   



    }Array;

    //创建

    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;

    }



    //销毁

    void destroy_array(Array* arr);

    {

        free(arr->ptr);

        free(arr);

    }

    //清空

    void clean(Array* arr);

    {

        arr->cnt=0;

    }

    //插入

    bool insert_array(Array* arr,int index,TYPE val);

    {

        //  判断表是否已满

        if(arr->cnt >= arr->cal)

        return false;

        //  判断下标是否能让表保持连续性

        if(index > arr->cnt)

        return false;

        /*

        for(int i=arr->cnt;i>index;i--)

        {

            arr->ptr[i] = arr->ptr[i-1];

        }

        */

        memmove(arr->ptr+index+1,arr->ptr+index,(arr->cnt-index)*sizeof(TYPE));

        arr->ptr[index] = val;

        arr->cnt++;

        return true;



    }

    //删除

    bool delete_array(Array* arr,size_t index);

    {

        if(index >= arr->cnt) return false;

        memmove(arr->ptr+index,arr->ptr+index+1,(arr->cnt-index-1)*sizeof(TYPE));

        arr->cnt--;

        return true;

    }

    //访问

    bool access_array(Array* arr,size_t index,TYPE* val);

    {

        if(index >= arr->cnt) return false;

        *val = arr->ptr[index];

        return true;



    }

    //查询

    int query_array(Array* arr,TYPE val);

    {

        for(int i=0;i<arr->cnt;i++)

        {

            if(val == arr->ptr[i])

            return i;

        }

        return -1;



    }

    //修改

    bool modify_array(Array* arr,int index,TYPE val);

    {

        if(index >= arr->cnt) return false;

        arr->ptr[index] = val;

        return true;



    }

    //排序

    void sort_array(Array* arr);

    {

        for(int i=0;i<arr->cnt-1;i++)

        {

            for(int j=i+1;j<arr->cnt;j++)

            {

                if(arr->ptr[i]>arr->ptr[j])

                TYPE temp = arr->ptr[i];

                arr->ptr[i] =arr->ptr[j];

                arr->ptr[j] = temp;

            }

        }



    }

    //遍历

    void show_array(Array* arr);

    {

        for(int i=0;i<arr->cnt;i++)

        {

            printf("&d ",arr->ptr[i]);

        }

        printf("\n");

    }

   

    int main()

    {

        Array* arr = create_array(10);

        for(int i=0;i<5;i+=)

        {

            insert_array(arr,0,i+1);

        }

        show_array(arr);

        insert_array(arr,5,8);

        show_array(arr);

        delete_array(arr,3)

        TYPE num = 0;

        access_array(arr,0,&num);

        printf("num=%d\n",num);

        printf("");

        sort_array(arr);

        show_array(arr);

        destroy_array(arr);

        arr NULL;



    }

    链式表:list

        元素(结点)的数据项:

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

            指针域:指向下一个结点

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

        不带头结点的单链表:

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

            缺点:添加、删除结点时,可能会修改指向第一个结点的指针,参数需要使用二级指针,才能更改指针的指向,比较麻烦


       

 #include <stdio.h>

        #include <stdlib.h>

        #include <stdbool.h>

        #define TYPE int



        //  设计链表的结点

        typedef struct Node

        {

            TYPE data;          //结点数据域

            struct  Node* next; //结点的指针域

        }Node;



        //  创建结点

       Node* create_node(TYPE data)

       {

            //  分配结点所需内存

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

            nade->data = data;

            node->next = NULL;

            return node;

   



       }

       //  头添加

       void add_head_list(Node** head, TYPE data)

       {

            Node* node = create_node(data);

            node->next = *head;

            *head = node;

       }

       // 按值删除

       bool del_value_list(Node** head,TYPE data)

       {

            if(data == (*head)->data)

            {

                Node* temp = *head;

                *head = temp->next;

                free(teamp);

                return true;

            }

            for(Node* n=*head;NULL != n->next;n=n->next)

            {

                //  要找的是待删除结点的上一个结点n

                if(data == n->next->data)

                {

                    //备份待删除结点

                    Node* teamp = n->next;

                    //连接待删除结点上一个和下一个

                    n->next = temp->next;

                    //释放待删除结点内存

                    free(teamp);

                    return true;

                }

            }

            return false;



       }

        //按位置删除

        bool del_index_list(Node** head,size_t index)

        {

            if(0 == index)

            {

                Node* teamp = *head;

                *head = teamp->next;

                free(teamp);

                return true;

            }

            // n是待删除结点上一个

            Node* n = *head;

            while(0 <--index)

            {

                n = n->next;

                if(NULL == n->next)

                return false;

            }

            // 找到了待删除结点 n->next

            Node* temp = n->next;

            n->next = temp->next;

            free(temp);

            return true;



        }

        //排序

        void sort_list(*Node head)

        {

            for(Node* n=head;NULL!=n->next;n=n->next)

            {

                for(Node* m=n->next;NULL!=m;m=m->next)

                {

                    if(n->data>m->data)

                    {

                        TYPE teamp = n->data;

                        n->data = m->data;

                        m->data = teamp;

                    }



                }

            }

        }

        //访问

        bool access_list(Node* head,int index,TYPE* val)

        {

            Node* node = head;

            for(int i=0;i<index;i++)

            {

                node = node->next;

                if(NULL == node) return false;

            }

            *val = node->data;

            return true;

        }



       //  遍历

       void show_list(Node* head)

       {

        for(Node* n=head; NULL!=n;n=n->next)

        {

            printf("%d",n->data);

        }

        printf("\n");

       }






        int main()

        {

            Node* head = NULL;

            for(int i=0;i<5;i++)

            {

                add_head_list(&head,i+1);

            }

            show_list(head);

            del_value_list(&head,5);

            show_list(head);

            del_index_list(&head,0);

            show_list(head);

            /*

            Node* n1 = create_node(1);

            Node* n2 = create_node(2);

            Node* n3 = create_node(3);

            Node* n4 = create_node(4);

            Node* n5 = create_node(5);



            n1->next = n2;

            n2->next = n3;

            n3->next = n4;

            n4->next = n5

           

            for(Node* n=n1;n!=NULL;n=n->next)

            {

                printf("%d ",n->data);

            }

            */



        }





    带头结点的单链表:

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

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

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



        #include <stdio.h>

        #include <stdlib.h>

        #include <stdbool.h>

        #define TYPE int



        //  设计链表的结点

        typedef struct Node

        {

            TYPE data;          //结点数据域

            struct  Node* next; //结点的指针域

        }Node;



        //  创建结点

       Node* create_node(TYPE data)

       {

            //  分配结点所需内存

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

            nade->data = data;

            node->next = NULL;

            return node;

       }

        //头添加

        void add_head_list(Node* head,TYPE val);

        {

            Node* node = create_node(val);

            node->next = head->next;

            head->next = node;

        }

        //尾添加

        void add_tail_list(Node* head,TYPE val);

        {

            Node* node = create_node(val);

            // n找到最后一个结点

            Node* n = head;

            while(NULL != n->next) n = n->next;

                    n->next = node;

        }

        //按值删除

        bool del_value_list(Node* head,TYPE val);

        {

                for(Node* n=head;NULL != n->next;n=n->next)

                {

                //  要找的是待删除结点的上一个结点n

                    if(val == n->next->data)

                    {

                        //备份待删除结点

                        Node* teamp = n->next;

                        //连接待删除结点上一个和下一个

                        n->next = temp->next;

                        //释放待删除结点内存

                        free(teamp);

                        return true;

                    }

                }

                return false;

        }

        //按位置删除

        bool del_index_list(Node* head,size_t index);

        {

            // n是待删除结点上一个

            Node n = head;

            if(NULL == n->next ) return false;

            while(i=0;i<index;i++)

            {

                n = n->next;

                if(NULL == n->next)

                return false;

            }

            // 找到了待删除结点 n->next

            Node* temp = n->next;

            n->next = temp->next;

            free(temp);

            return true;



        }



        //插入

        bool insert_list(Node* head,size_t index,TYPE val);

        {

            Node* n = head;

            // 不进行头添加

            if(NULL == n->next || inde == 0) return false;

            for(int i = 0;i<index;i++)

            {

                n = n->next;

                // 不进行尾添加

                if(NULL == n->next) return false;

            }

            Node* node = create_node(val);

            node->next = n->next;

            n->next = node;

            return true;    

        }



        //修改

        bool modify_list(Node* head,TYPE old,TYPE val);

        {

            for(Node* n=head->next;NULL != n;n=n->next)

            {

                if(old == n->data)

                {

                    n->data = val;

                    return true;

                }

            }

            return false;

        }

        //访问

        bool access_list(Node* head,size_t index,TYPE* val);

        {

            Node* n = head->next;

            if(NULL == n) return false;

            for(int i=0;i<index;i++)

            {

                n=n->next;

                if(NULL == n) return false;

            }

            *val = n->data;

            return true;

        }

        //查找

        int query_list(Node* head,TYPE val);

        {

            Node* n = head->next;

            for(int i=0;NULL != n;i++

            )

            {

                if(n->data == val)    

                    return i;

                    n = n->next

            }

            return -1;

        }

        //排序

        void sort_list(Node* head);

        {

            for(Node* n=head->next;NULL!=n->next;n=n->next)

            {

                for(Node* m=n->next;NULL!=m;m=m->next)

                {

                    if(n->data>m->data)

                    {

                        TYPE teamp = n->data;

                        n->data = m->data;

                        m->data = teamp;

                    }



                }

            }

        }

       




        void show_list(Node* head)

        {

            for(Node* n = head->next;NULL != n;n = n->next)

            {

                printf("%d ",n->data);

            }

            printf("\n");

        }

       int main()

       {

        // head就是带头结点链表的头结点,head->next永远指向第一个有效数据的结点

        Node* head = create_node(0);

        for(int i=0;i<10;i++)

        {

            add_head_list(head,rand()%100);

        }

       }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaoyu1381

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值