数据结构学习小结(day01)

1.数据结构基本概念

数据结构是相互之间存在一种或多种特定关系的数据元素的集合。它是计算机存储、组织数据的方式,直接影响程序的效率和性能。

2.数据结构分类

1.逻辑结构
  • 集合结构:所有数据都在一个集合中,元素间关系平等。
  • 线性结构:数据之间是一对一的关系,如数组、链表。
  • 树状结构:数据之间是一对多的关系,如二叉树、B树。
  • 图状结构:数据之间是多对多的关系,如社交网络图。
2.物理结构(存储结构)
  • 顺序存储:数据存储在连续的存储单元中,如数组。
  • 链式存储:数据存储单元可以是任意的,通过指针连接,如链表。

2.抽象数据类型 (ADT)

抽象数据类型是数学模型与操作的结合,即数据与算法的结合。它定义了数据的逻辑结构及其操作,而不涉及具体的实现细节。

3.算法基础

1.算法定义

算法是解决特定问题求解步骤的描述,在计算机中表现为指令的有限序列。

1.算法特征
  • 输入输出:算法必须有输出。
  • 有穷性:执行步骤会自动结束,且每一步在可接受时间内完成。
  • 确定性:相同输入产生相同输出。
  • 可行性:每一步都可实现。
算法设计原则
  • 正确性:语法正确,合法输入产生合理输出,对非法输入能给出适当响应,通过各种测试用例。
  • 可读性:便于交流、阅读和理解。
  • 健壮性:能处理非法输入而不产生异常。
  • 高效性:低存储需求,高执行效率。

4.时间复杂度分析

1.推导规则
  • 用常数1取代运行时间中所有加法常数。
  • 只保留最高阶项。
  • 如果最高阶项系数不为1,去除该系数。
2.常见时间复杂度排序

O(1) < O(logn) < O(n) < O(nlogn) < O(n²) < O(n³) < O(n!) < O(nⁿ)

5.线性表概述

线性表是零个或多个数据元素的有限序列,具有以下特性:

  • 元素之间是有顺序的。
  • 如果存在多个元素:
    • 第一个元素无前驱。
    • 最后一个元素没有后继。
    • 每个元素只有一个前驱和一个后继。
  • 线性表的元素个数n(n≥0)称为线性表的长度。
  • n=0时为空表。
  • 非空表中每个元素都有一个确定的位置。

6.顺序表实现

顺序表是在计算机内存中以数组形式保存的线性表,用一组地址连续的存储单元依次存储数据元素。

顺序表ADT(抽象数据类型)
typedef struct 
{
    DATATYPE *data;  // 存储数据的数组
    int length;      // 当前长度
    int capacity;    // 总容量
} SeqList;
7.基本操作实现
1.创建顺序表
SeqList *CreateSeqList(int len) 
{
    SeqList *list = (SeqList *)malloc(sizeof(SeqList));
    if (list == NULL) 
    {
        return NULL;
    }
    
    list->data = (DATATYPE *)malloc(sizeof(DATATYPE) * len);
    if (list->data == NULL) 
    {
        free(list);
        return NULL;
    }
    
    list->length = 0;
    list->capacity = len;
    return list;
}
2.显示顺序表
int ShowSeqList(SeqList *list) 
{
    if (list == NULL || list->data == NULL) 
    {
        return -1;
    }
    
    printf("SeqList: [");
    for (int i = 0; i < list->length; i++) 
    {
        // 假设DATATYPE有打印方法
        printf("%s", list->data[i].name);
        if (i < list->length - 1) 
        {
            printf(", ");
        }
    }
    printf("]\n");
    return 0;
}
3.尾插元素
int InsertTailSeqList(SeqList *list, DATATYPE data) 
{
    if (list == NULL || IsFullSeqList(list)) 
    {
        return -1;
    }
    
    list->data[list->length] = data;
    list->length++;
    return 0;
}
4.判断顺序表是否已满
int IsFullSeqList(SeqList *list) 
{
    if (list == NULL) 
    {
        return -1;
    }
    return list->length >= list->capacity;
}
5.判断顺序表是否为空
int IsEmptySeqList(SeqList *list) 
{
    if (list == NULL) 
    {
        return -1;
    }
    return list->length == 0;
}
6.按位置插入元素
int InsertPosSeqList(SeqList *list, DATATYPE data, int pos) 
{
    if (list == NULL || pos < 0 || pos > list->length || IsFullSeqList(list)) 
    {
        return -1;
    }
    
    // 将pos及之后的元素后移
    for (int i = list->length; i > pos; i--) 
    {
        list->data[i] = list->data[i-1];
    }
    
    list->data[pos] = data;
    list->length++;
    return 0;
}
7.查找元素
int FindSeqList(SeqList *list, char *name) 
{
    if (list == NULL || name == NULL) 
    {
        return -1;
    }
    
    for (int i = 0; i < list->length; i++) 
     {
        if (strcmp(list->data[i].name, name) == 0) 
        {
            return i;  // 返回找到的位置
        }
    }
    return -1;  // 未找到
}
8.修改元素
int ModifySeqList(SeqList *list, char *old, DATATYPE new) 
{
    int pos = FindSeqList(list, old);
    if (pos == -1) 
    {
        return -1;
    }
    
    list->data[pos] = new;
    return 0;
}
9.删除元素
int DeleteSeqList(SeqList *list, char *name) 
{
    int pos = FindSeqList(list, name);
    if (pos == -1) 
    {
        return -1;
    }
    
    // 将pos之后的元素前移
    for (int i = pos; i < list->length - 1; i++) 
    {
        list->data[i] = list->data[i+1];
    }
    
    list->length--;
    return 0;
}
10.获取顺序表长度
int GetSeqListLen(SeqList *list) {
    if (list == NULL) {
        return -1;
    }
    return list->length;
}
11.获取指定位置元素
DATATYPE *GetItemSeqList(SeqList *list, int ind) 
{
    if (list == NULL || ind < 0 || ind >= list->length) 
    {
        return NULL;
    }
    return &(list->data[ind]);
}

12.主程序示例

int main() {
    // 创建容量为10的顺序表
    SeqList *list = CreateSeqList(10);
    if (list == NULL) {
        printf("Create list failed!\n");
        return -1;
    }
    
    // 插入数据
    DATATYPE data1 = {"Alice"};
    DATATYPE data2 = {"Bob"};
    DATATYPE data3 = {"Charlie"};
    
    InsertTailSeqList(list, data1);
    InsertTailSeqList(list, data2);
    InsertPosSeqList(list, data3, 1);
    
    // 显示顺序表
    ShowSeqList(list);
    
    // 查找元素
    int pos = FindSeqList(list, "Bob");
    if (pos != -1) {
        printf("Found Bob at position %d\n", pos);
    }
    
    // 修改元素
    DATATYPE newData = {"Bobby"};
    ModifySeqList(list, "Bob", newData);
    
    // 删除元素
    DeleteSeqList(list, "Alice");
    
    // 再次显示
    ShowSeqList(list);
    
    // 销毁顺序表
    DestroySeqList(list);
    
    return 0;
}

总结

顺序表是线性表的一种实现方式,具有以下特点:

  • 随机访问效率高,通过下标可直接访问元素。
  • 插入和删除操作需要移动大量元素,效率较低。
  • 需要预先分配固定大小的存储空间。

在实际应用中,应根据具体需求选择合适的线性表实现方式(顺序表或链表)。顺序表适合元素数量固定或需要频繁随机访问的场景,而链表则更适合频繁插入删除操作的场景。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值