数据结构-顺序表

1、线性表的基本概念

(1)线性结构是简单而且常用的数据结构,而线性表则是一种典型的线性结构。

(2)线性表:是具有相同数据类型的n个数据元素的有限序列

(3)线性表的存储结构:顺序存储结构:顺序表        链式存储结构:链表

操作数据结构的思路:创销——针对表、增删改查——针对数据

2、顺序表           逻辑顺序和物理结构一致

1.数据结构是计算机存储,管理数据的方式。
2.数据结构研究的就是这种数据的存储结构(物理结构)和数据的逻辑结构。
3.数据逻辑结构
(1)集合                     元素之间没有任何逻辑关系
(2)线性结构              元素之间存在一对一
(3)树型结构              元素之间存在一对多
(4)图形结构              元素之间存在多对多
4.数据存储结构
(1)顺序存储        (逻辑顺序和存储顺序一致)
(2)链式存储        (逻辑顺序和存储顺序不在乎一致)
(3)索引存储
(4)散列存储
5.线性表:具有相同数据类型的n个有限序列组成
逻辑结构:线性结构
存储结构:顺序存储====>顺序表      链式存储====>链表

线性表的特点:围绕一对一关系的描述
6.顺序表:
(1)常用操作:创建、销毁、增删改查
1.创建顺序表结构体类型—需要用户自定义
顺序表的实现方式:1.通过数组  2.通过指针

顺序表的特点:
(1)顺序表的元素是按顺序进行存储的
(2)顺序表比较擅长随机访问和遍历
(3)不擅长动态删除增加,需要移动大量元素

7.顺序表和数组进行对比
1、数组是一种特殊的顺序表
2、顺序表是通过数组来实现的,顺序表的元素存储在一块连续的存储空间里
3、数组的长度是不可变的,顺序表的长度是可以改变的

2.1、项目练习:   通过数组创建顺序表结构体类型

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//1.创建顺序表结构体类型
#define MAX_SIZE 100
typedef int elementType;//将int类型重命名为elementType
typedef struct OrderList {

    //1.通过数组创建
    elementType data[MAX_SIZE];//存放顺序表元素的数组
    int length;//存放顺序表元素的个数
}OrderList; 

//声明函数
void print_menu(void);
OrderList* create_list();
void printf_list(OrderList* List);
void append_list(OrderList* List,elementType val);
void insert_list(OrderList* List, int index, elementType val);
void delete_List(OrderList* List, int index);
void change_List(OrderList* List, int index, elementType val);
void destroy_List(OrderList** List);


int main() {
    print_menu();//调用菜单函数
    int order=0;//接收用户操作的指令
    elementType val = 0;//数组中的元素
    int index = 0;//数组的索引下标

    //定义顺序表结构体指针
    OrderList* List = NULL;   //内存动态分配,需要手动释放

    while (1) {
        printf("请输入您的操作指令:");
        scanf("%d", &order);
        switch (order) {
        case 1:
            //创建顺序表
            List = create_list();
            break;
        case 2:
            //打印顺序表
            printf_list(List);
            break;
        case 3:
            //追加一个节点        从尾部追加
            printf("请输入您要追加的元素:");
            scanf("%d", &val);
            append_list(List,val);
            break;
        case 4:
            //插入一个节点            随机插入(从0开始)
            printf("请输入您要插入的位置:");
            scanf("%d", &index);
            printf("请输入您要插入的元素:");
            scanf("%d", &val);
            insert_list(List,index,val);        //三个参数分别为表、插入位置、插入的数据
            break;
        case 5:
            //删除一个节点         用户输入删除的索引,默认从0开始
            printf("请输入您要删除的位置:");
            scanf("%d", &index);
            delete_List(List, index);
            break;
        case 6:
            //修改顺序表元素        用户输入修改的索引,默认从0开始
            printf("请输入您要修改的位置:");
            scanf("%d", &index);
            printf("请输入修改后的元素:");
            scanf("%d", &val);
            change_List(List, index, val);
            break;
        case 7:
            //销毁顺序表
            destroy_List(&List);    //传地址
            break;
        case 8:
            //退出
            return;
        default:
            printf("输入指令有误,请重新输入!\n");
        }
    }
    return 0;
}

//打印菜单
void print_menu(void) {
    system("cls");//系统函数 用于屏幕清空
    printf("操作指令说明:\n");
    printf("1:创建顺序表\n2:打印顺序表\n");
    printf("3:追加一个节点\n4:插入一个节点\n");
    printf("5:删除一个节点\n6:修改顺序表元素\n");
    printf("7:销毁顺序表\n8:退出\n");
}

//1.创建顺序表的函数
OrderList* create_list() {
    OrderList* List = (OrderList*)malloc(sizeof(OrderList));//动态创建顺序表
    //申请失败
    if (List == NULL) {
        printf("创建失败!\n");
        return NULL;
    }
    //申请成功  先清0

    //memset()  一般用于数组清0,需引入memory.h/string.h


    memset(List, 0, sizeof(OrderList)); 
    List->length = 0;
    printf("初始化成功\n");
    return List;
}

//2.打印顺序表的函数
void printf_list(OrderList* List) {
    //判断顺序表是否存在
    if (List == NULL) {
        printf("顺序表不存在,请先创建!\n");
        return;
    }
    //判断顺序表是否为空
    if (!List->length) {
        printf("顺序表为空,无法打印!\n");
        return;
    }
    //正常打印
    for (int i = 0;i < List->length;i++) {
        printf("%d ", List->data[i]);
    }
    printf("\n");
}

//3.追加一个节点    从索引0开始
void append_list(OrderList* List, elementType val) {
    //判断顺序表是否存在
    if (List == NULL) {
        printf("顺序表不存在,请先创建!\n");
        return;
    }
    //判断是否内存是否占满
    if (List->length >= MAX_SIZE) {
        printf("内存已满,无法追加\n");
        return;
    }
    //正常追加
    List->data[List->length] = val;      //将数据存放在数组的最后
    List->length++;
    printf("数据追加成功!\n");
}

//4.插入一个节点      从索引0开始
void insert_list(OrderList* List, int index, elementType val) {
    //判断顺序表是否存在
    if (List == NULL) {
        printf("顺序表不存在,请先创建!\n");
        return;
    }
    //判断是否内存是否占满
    if (List->length >= MAX_SIZE-1) {
        printf("内存已满,无法追加\n");
        return;
    }
    //正常插入数据
    for (int i = List->length;i >= index;i--) {
        List->data[i + 1] = List->data[i];        
    }
    List->data[index] = val;
    List->length++;
    printf("数据插入成功!\n");
}

//5.删除一个节点      从索引0开始
void delete_List(OrderList* List, int index) {
    //判断顺序表是否存在
    if (List == NULL) {
        printf("顺序表不存在,请先创建!\n");
        return;
    }
    //判断输入的位置即索引值是否合法
    if (index<0 || index>= List->length) {
        printf("输入的位置不合法!\n");
        return;
    }
    //正常删除
    for (int i = index;i < List->length;i++) {
        List->data[i] = List->data[i + 1];
    }
    List->length--;
    printf("数据删除成功!\n");
}

//6.修改顺序表元素      从索引0开始
void change_List(OrderList* List, int index, elementType val) {
    //判断顺序表是否存在
    if (List == NULL) {
        printf("顺序表不存在,请先创建!\n");
        return;
    }
    //正常修改
    List->data[index] = val;
    printf("数据修改成功!\n");
}

//7.销毁          注意:形参是二级指针
void destroy_List(OrderList** List) {
    free(*List);
    *List = NULL;
    printf("顺序表已销毁!\n");
}

2.2、指针实现顺序表

2.2.1、mian.c

 #include <stdio.h>
#include "03.h"
int main() {
    fn2();
    return 0;
}

2.2.2、03.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
//顺序表的指针实现方式
//定义结构体
typedef int ElemenT;
typedef struct OrderListPtr {
    ElemenT* datap;//元素类型指针  用于申请内存后存放数组元素
    int length;//存放数组元素的个数
}ODP;

void fn2(void);
void create_List(ODP* List);
void printf_menu(void);
void append_List(ODP* List, ElemenT val);
void printf_List(ODP List);
void insert_List(ODP* List, int index, ElemenT val);
void delete_List(ODP* List, int index);
void edit_List(ODP* List, int index, ElemenT val);
void destory_List(ODP* List);

 2.2.3、03.c

#include "03.h"
#define MAX_SIZE 100


void fn2(void) {

    int order = 0;//存储操作指令
    printf_menu();//调用菜单函数
    ODP List = {NULL,0};    //定义结构体变量
    ElemenT val = 0;
    int index = 0;


    while (1) {
        printf("请输入操作指令:");
        scanf("%d", &order);
        switch (order) {
        case 1:
            //创建空表
            create_List(&List);//分配一块连续的空间
            break;
        case 2:
            //打印顺序表
            printf_List(List);
            break;
        case 3:
            //追加一个节点
            printf("请输入要追加的元素");
            scanf("%d", &val);
            append_List(&List, val);
            break;
        case 4:
            //插入一个节点
            printf("请输入要插入的位置:");
            scanf("%d", &index);
            printf("请输入要插入的元素");
            scanf("%d", &val);
            insert_List(&List, index, val);//表,位置,插入的是谁
            break;
        case 5:
            //删除一个节点
            printf("您要删除位置:");
            scanf("%d", &index);
            delete_List(&List, index);
            break;
        case 6:
            //修改顺序表元素
            printf("请输入要修改的元素位置");
            scanf("%d", &index);
            printf("请输入修改后的新值:");
            scanf("%d", &val);
            edit_List(&List, index, val);
            break;
        case 7:
            //销毁顺序表
            destory_List(&List);//传地址
            break;
        case 8:
            //退出
            return;
        default:
            printf("输入指令有误,请重新输入\n");
        }
    }

}

//打印菜单
void printf_menu(void) {
    system("cls");//系统函数 用于屏幕清空
    printf("操作指令说明:\n");
    printf("1:创建顺序表\n2:打印顺序表\n");
    printf("3:追加一个节点\n4:插入一个节点\n");
    printf("5:删除一个节点\n6:修改顺序表元素\n");
    printf("7:销毁顺序表\n8:退出\n");
}

//初始化一个空表
void create_List(ODP* List) {
    //申请内存空间
    List->datap = (ElemenT*)malloc(sizeof(ElemenT) * MAX_SIZE);
    if (!List->datap) {
        printf("内存申请失败\n");
        return;
    }
    //清0操作
    memset(List->datap, 0, sizeof(ElemenT) * MAX_SIZE);
    List->length = 0;
    printf("初始化成功!\n");
}


//追加函数
void append_List(ODP* List, ElemenT val) {
    //判断是否建过表
    if (!List->datap) {
        printf("请先建表\n");
        return;
    }
    //判断表是否满
    if (List->length >= MAX_SIZE) {
        printf("表已满,无法追加!\n");
        return;
    }
    //正常追加
    *(List->datap + List->length) = val;

    //追加方法二
    //List->datap[List->length] = val;
    List->length++;
    printf("追加成功\n");
}

//打印顺序表
void printf_List(ODP List) {
    //判断是否建过表
    if (!List.datap) {
        printf("请先建表\n");
        return;
    }
    if (List.length == 0) {
        printf("空表,无法打印\n");
        return;
    }
    for (int i = 0;i < List.length;i++) {
        printf("%d ", List.datap[i]);//数组
        //printf("%d ", *(List.datap+i));//指针
    }
    printf("\n");
}


//插入操作
void insert_List(ODP* List, int index, ElemenT val) {
    //判断是否建过表
    if (!List->datap) {
        printf("请先建表\n");
        return;
    }
    //判断表是否满
    if (List->length >=MAX_SIZE) {
        printf("表已满,无法追加\n");
        return;
    }

    //正常插入  从index倒序遍历,位置后移 
    //判断插入的位置是否合法
    if (index<0 || index>List->length - 1) {
        printf("插入位置不合法\n");
        return;
    }
    for (int i = List->length - 1;i >= index;i--) {
        List->datap[i + 1] = List->datap[i];
    }    
        //数组
        List->datap[index] = val;
        //指针
        //*(List->datap + index) = val;
        List->length++;
        printf("插入成功!\n");
}


//删除函数
void delete_List(ODP* List, int index) {
    //判断是否建过表
    if (!List->datap) {
        printf("请先建表\n");
        return;
    }
    if (List->length == 0) {
        printf("空表,无法删除\n");
        return;
    }
    //判断要删除的元素位置是否合法
    int ind = index - 1;//要删除的元素索引
    if (ind<0 || ind>List->length - 1) {
        printf("您要删除的元素不存在\n");
        return;
    }
    //正常删除     从ind+1开始,所有的元素前移 
    for (int i = ind;i < List->length;i++) {
        List->datap[i] = List->datap[i + 1];
    }
    List->length--;
    printf("删除成功!\n");
}

//修改函数
void edit_List(ODP* List, int index, ElemenT val) {
    //判断是否建过表
    if (!List->datap) {
        printf("请先建表\n");
        return;
    }
    if (List->length == 0) {
        printf("空表,无法修改\n");
        return;
    }
    //判断要修改的元素位置是否合法
    int ind = index - 1;//要修改的元素索引
    if (ind<0 || ind>List->length - 1) {
        printf("您要修改的元素不存在\n");
        return;
    }
    //正常修改
    List->datap[ind] = val;
    // *(List->datap + ind) = val;
    printf("修改成功!\n");
}

//销毁   注意:形参是二级指针
void destory_List(ODP* List) {
    free(List->datap);//释放内存空间
    List->datap = NULL;//销毁前要置空
    List->length = 0;//元素置0
    printf("销毁成功!\n");
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值