数据结构笔记1:线性(顺序表)表的模板(非伪代码)

一、思路分块解析

1. 头文件和数据结构定义

typedef struct {
    int *elements;   // 存储元素的数组,使用动态分配的内存存放数据
    int capacity;    // 数组的总容量,即当前能存储的最大元素数
    int size;        // 当前数组中实际存储的元素个数
} ConsequenceList;
  • 数据结构 ConsequenceList
    这是一个顺序表(类似动态数组)的实现:
    • elements:指向存放整型数据的动态内存区域。
    • capacity:当前内存分配的容量,用于判断是否需要扩容。
    • size:实际存储的元素数量,用于插入、删除和查找操作时作为有效数据的范围。

2. 顺序表的创建与销毁

2.1 创建顺序表

void Creat_ConsequenceList(ConsequenceList * list, int capacity)
{
    list->elements = (int *)malloc(sizeof(int) * capacity);
    list->capacity = capacity;
    list->size = 0;
}
  • 功能说明
    • 动态分配一个大小为 capacity 的整型数组,用于存储数据。
    • capacity 保存到结构体中,并初始化当前元素个数 size 为 0。

2.2 销毁顺序表

void Destory_ConsequenceList(ConsequenceList* list)
{
    if (list->elements)
    {
        free(list->elements);
        list->elements = NULL;
    }
}
  • 功能说明
    • 释放动态分配的内存,并将指针置为 NULL,避免悬空指针问题。

3. 顺序表的基本操作

3.1 获取顺序表的大小

int GetSize_ConsequenceList(ConsequenceList * list)
{
    return list->size;
}
  • 功能说明
    • 返回当前顺序表中实际存储的元素个数。

3.2 插入元素

void Add_ConsequenceList(ConsequenceList* list, int index, int element)
{
    if (index < 0 || index > list->capacity) // 检查下标是否合法
    {
        printf("不合法的下标索求");
        return;
    }
    if (index == list->capacity) // 如果下标等于容量,说明需要扩容
    {
        int *New_elements = realloc(list->elements, sizeof(int) * list->capacity * 2); // 扩容为原来的两倍
        list->elements = New_elements;
        list->capacity *= 2;
    }
    // 将下标 index 之后的元素向后移动,为新元素腾出空间
    for (int i = list->size; i > index; i--)
    {
        list->elements[i] = list->elements[i - 1];
    }
    list->elements[index] = element; // 在指定位置插入新元素
    list->size++;
}
  • 功能说明
    1. 下标检查
      • 判断插入位置是否合法,若 index < 0 或大于 capacity 则认为不合法。
    2. 扩容操作
      • 如果插入位置等于当前容量(表明数组已满或达到预设容量边界),使用 realloc 将内存扩大为原来的两倍,并更新 capacity
    3. 数据移动
      • 从尾部开始,将元素逐个后移一位,为新元素腾出空位。
    4. 插入元素
      • 将新元素放到指定位置,并将 size 增加 1。

注意:
代码中判断扩容的条件是 if (index == list->capacity),这要求插入的下标必须与当前容量相等才触发扩容,而通常插入操作应判断是否达到 size(已存元素个数)是否与 capacity 相等。此处逻辑有一定局限性,实际使用时需注意下标的合理性和扩容的条件。

3.3 删除元素

void Delete_ConsequenceList(ConsequenceList* list, int index)
{
    if (index < 0 || index >= list->size) // 判断下标是否合法
    {
        printf("不合法的下标索求");
        return;
    }
    // 将 index 后面的所有元素前移覆盖删除的元素
    for (int i = index; i < list->size; i++)
    {
        list->elements[i] = list->elements[i + 1];
    }
    list->size--;
}
  • 功能说明
    1. 下标检查
      • 确保待删除位置在有效范围内(0size-1)。
    2. 数据移动
      • 从删除位置开始,将后面的元素前移覆盖删除元素,保持数组连续性。
    3. 更新大小
      • 删除元素后,将 size 减 1。

3.4 修改元素

void Change_ConsequenceList(ConsequenceList* list, int index, int element)
{
    if (index < 0 || index >= list->size) // 判断下标是否合法
    {
        printf("不合法的下标索求");
        return;
    }
    list->elements[index] = element;
}
  • 功能说明
    • 根据指定下标修改元素的值,前提是下标在合法范围内。

3.5 查找元素

void Find_ConsequenceList(ConsequenceList* list, int element)
{
    int index; // 用来存储找到的下标
    for (int i = 0; i < list->size; i++)
    {
        if (element == list->elements[i]) // 如果找到了对应的元素
        {
            index = i;
            printf("第%d的值为%d\n", index, list->elements[index]);
            return;
        }
    }
    printf("找不到对应的元素\n");
}
  • 功能说明
    • 依次遍历数组,若找到与目标值相同的元素则打印其下标和值,并结束函数。
    • 如果遍历完成后没有找到,则输出提示信息。

4. 主函数 main

int main()
{
    ConsequenceList list;
    Creat_ConsequenceList(&list, 1);
 
    for (int i = 0; i <10; i++)
    {
        Add_ConsequenceList(&list, i, i * 10);
        printf("%d %d\n", i, list.elements[i]);
    }
    printf("Size:%d\n", list.size);
 
    Find_ConsequenceList(&list, 50);
    Change_ConsequenceList(&list, 4, 80);
 
    Delete_ConsequenceList(&list, 8);
    for (int i = 0; i < list.size; i++)
    {
        printf("%d %d\n", i, list.elements[i]);
    }
    
    system("pause");
    return 0;
}

4.1 初始化与插入元素

  • 初始化顺序表

    • 调用 Creat_ConsequenceList 创建一个初始容量为 1 的顺序表。
      • 初始容量设为 1,但在插入时会自动扩容。
  • 循环插入元素

    • 循环 10 次,每次调用 Add_ConsequenceList(&list, i, i * 10)
      • 插入位置为当前索引 i,插入的值为 i*10(例如:0, 10, 20, …)。
    • 每次插入后打印当前插入的索引和对应的值。

4.2 展示顺序表的大小

  • 打印 list.size,显示当前存储的元素数量。

4.3 查找、修改和删除操作

  • 查找操作

    • 调用 Find_ConsequenceList(&list, 50),在数组中查找值为 50 的元素并打印其下标和值。
  • 修改操作

    • 调用 Change_ConsequenceList(&list, 4, 80),将下标 4 的元素修改为 80。
  • 删除操作

    • 调用 Delete_ConsequenceList(&list, 8),删除下标 8 处的元素,随后数组中后面的元素会自动前移。

4.4 打印最终的数组内容

  • 遍历顺序表,打印每个下标及对应的元素值,展示修改与删除后的结果。

4.5 退出程序前的暂停

  • 调用 system("pause"),使程序在结束前暂停,方便在 Windows 系统上观察控制台输出。

总结

这段代码实现了一个简单的顺序表(动态数组)的基本操作,包括创建、扩容、插入、删除、修改和查找。主要特点如下:

  • 动态内存分配与扩容:
    利用 mallocrealloc 动态分配内存,并在需要时扩充容量。

  • 数据移动:
    插入和删除操作时需要将数组中数据移动,以保持元素的连续性。

  • 错误处理:
    通过下标合法性检查防止数组越界,但在扩容条件判断上存在一定局限(实际应用中可能需要根据 size 而非 capacity 判断是否扩容)。

二、完整代码实现

#include<stdio.h>
#include<stdlib.h>
 
typedef struct {
	int *elements; //元素数组
	int  capacity; //总的容量大小
	int  size;  //元素总数
}ConsequenceList;
 
void Creat_ConsequenceList(ConsequenceList * list,int capacity) 
//创建一个容量capacity固定的顺序表
{
	list->elements = (int *)malloc(sizeof(int) * capacity);
	list->capacity = capacity;
	list->size = 0;
}
 
void Destory_ConsequenceList(ConsequenceList* list)
//删除顺序表
{
	if (list->elements)
	{
		free(list->elements);
		list->elements = NULL;
	}
}
 
int GetSize_ConsequenceList(ConsequenceList * list)
//获取元素的个数
{
	return list->size;
 
}
//增加元素
void Add_ConsequenceList(ConsequenceList* list,int index,int element)
{
	if (index < 0 || index > list->capacity) //下标不合法
	{
		printf("不合法的下标索求");
		return;
	}
	if (index == list->capacity) //表明此时需要扩容
	{
		int *New_elements=realloc(list->elements, sizeof(int) * list->capacity * 2);//扩容一倍
		list->elements = New_elements;
		list->capacity *= 2;
	}
	for (int i = list->size; i > index; i--) //数组整体往后挪
	{
		list->elements[i] = list->elements[i - 1];
	}
	list->elements[index] = element;//修改对应下标的值
	list->size++;
}
 
//删除元素
void Delete_ConsequenceList(ConsequenceList* list, int index)
{
	if (index < 0 || index >= list->size) //下标不合法
	{
		printf("不合法的下标索求");
		return;
	}
	for (int i = index; i < list->size; i++)
	{
		list->elements[i] = list->elements[i + 1];//整体往前覆盖
	}
	list->size--;
}
//修改元素
void Change_ConsequenceList(ConsequenceList* list, int index, int element)
{
	if (index < 0 || index >= list->size) //下标不合法
	{
		printf("不合法的下标索求");
		return;
	}
	list->elements[index] = element;
}
 
//查找元素
void Find_ConsequenceList(ConsequenceList* list, int element)
{
	int index;//用来存储寻找元素的下标
	
	for (int i = 0; i < list->size; i++)
	{
		if (element == list->elements[i])//找到了
		{
			index = i;
			printf("第%d的值为%d\n", index, list->elements[index]);
			return;
		}
	}
 
	printf("找不到对应的元素\n");
}
 
int main()
{
	ConsequenceList list;
	Creat_ConsequenceList(&list, 1);
 
	for (int i = 0; i <10; i++)
	{
		Add_ConsequenceList(&list, i, i * 10);
		printf("%d %d\n", i, list.elements[i]);
	}
	printf("Size:%d\n", list.size);
 
	Find_ConsequenceList(&list, 50);
	Change_ConsequenceList(&list, 4, 80);
 
	Delete_ConsequenceList(&list, 8);
	for (int i = 0; i < list.size; i++)
	{
		printf("%d %d\n", i, list.elements[i]);
	}
	
	system("pause");
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值