C语言-数据结构-动态顺序表

2 篇文章 0 订阅
1 篇文章 0 订阅

本代码编辑在CLion环境上,若要复制代码运行起来需要修改一些地方。

代码分为 3 个部分,头文件 list.h, 实现头文件的 list.c 和 main.c 文件。

大部分代码都有注释,但是没有配合对应的图解,需要在读代码是自己构想。

代码纯手写,如有不足之处,请多指教

main.c 部分

#include <stdio.h>
#include "list.h"

int main() {
    struct list* list = list_init();
    list_add(list, 99);
    list_print(list);
    list_add(list, 78);
    list_insert(list, 0, 88);
    list_print(list);
    list_add(list, 100);
    list_print(list);
    int e;
    list_remove(list, 1, &e);
    list_print(list);
    printf("%d %d\n", list_get(list, 1), list_get(list, 2));
    list_set(list, 0, 5);
    list_print(list);

    list_free(list);
    return 0;
}

list.h 部分

//
// Created by Sur qing on 2022/5/17.
//

#ifndef SEQUENCE_LIST_H
#define SEQUENCE_LIST_H

struct list;


/*
   功能:在堆里创建一个空的线性表,成功返回有效指针,失败返回NULL。
   前提条件:无。
*/
struct list* list_init();


/*
   功能:释放线性表list
   前提条件:list必须是有效指针
*/
void list_free(struct list* list);


/*
   功能:返回线性表list的数据元素个数
   前提条件:list必须是有效指针
   后置条件:数据元素个数必须 >= 0
*/
int list_count(struct list* list);


/*
   功能:清空线性表list中的数据元素
   前提条件:list必须是有效指针
   后置条件:数据元素个数必须==0
*/
void list_clear(struct list* list);


/*
   功能:判断线性表list是否为空,为空返回 1,否则返回 0
   前提条件:list必须是有效指针
   后置条件:无
*/
int list_isEmpty(struct list* list);


/*
   功能:在线性表list查找元素e,找到返回 1,否则返回 0
   前提条件:list必须是有效指针
   后置条件:无
*/
int list_contains(struct list* list, int e);


/*
   功能:在线性表list的index位置插入元素e,成功返回 1 ,失败返回 0
   前提条件:1. list必须是有效指针
            2. index>=0 && index <= count
   后置条件:数据元素的个数count+1
*/
int list_insert(struct list* list, int index, int e);


/*
   功能:在线性表list的末尾插入元素e
   前提条件:list必须是有效指针
   后置条件:数据元素的个数count+1
*/
void list_add(struct list* list, int e);


/*
   功能:在线性表list的index位置写入元素e
   前提条件:1. list必须是有效指针
             2. index>=0 && index < count
   后置条件:list[index] == e
*/
int list_set(struct list* list, int index, int e);


/*
   功能:删除线性表list的index位置,被删除的元素写入参数e
   前提条件:1. list必须是有效指针
             2. index>=0 && index < count
   后置条件:count-1
*/
void list_remove(struct list* list, int index, int* e);


/*
   功能:返回线性表list的index位置的元素
   前提条件:1. list必须是有效指针
             2. index>=0 && index < count
   后置条件:
*/
int list_get(struct list* list, int index);


/*
   功能:打印出list中所有的元素
   前提条件:1. list必须是有效指针
   后置条件:
*/
void list_print(struct list* list);

#endif //SEQUENCE_LIST_H

list.c 部分

//
// Created by Sur qing on 2022/5/17.
//

#include <assert.h>
#include "stdlib.h"
#include "stdio.h"

#include "list.h"


#define INIT_SIZE 50
#define INCR_SIZE 50

// 定义 list 结构体
struct list {
    int *data;
    int size;
    int count;
};

struct list* list_init() {
    // 为 list 结构体分配内存
    struct list* list = NULL;
    list = (struct list*) malloc(sizeof(struct list));
    assert(list != NULL);
    /*
     * 通过 assert 可以更方便我们 Debug,
     * malloc, calloc, realloc 三个函数在执行时,在某些情况下会申请内存失败
     * 而返回一个 NULL 指针,在这里通过 对 list 不为空的断言可以确保我们
     * 后续的正常操作不会出现错误,同理后面类似
     * */

    // 将 list 结构体初始化
    list->data = NULL;
    list->data = (int*) calloc(INIT_SIZE, sizeof(int));
    assert(list->data);
    /*
     * 这里还有存在一个细节问题,不过不能理解也没关系。
     * 如果此时 list->data 的内存申请失败,断言会直接结束程序
     * 那会出现一个问题,就是之前 list = (struct list*) malloc(sizeof(struct list));
     * 申请的内存不会被释放,如何解决?
     * 在断言之前应该在加一句判断:如果 list->data == NULL,
     * 那么先将之前分配的内存先释放后在,再结束程序
     * 同理在后面的代码中某些位置也会有类似的问题,就不在叙述了
     * */
    list->size = INIT_SIZE;
    list->count = 0;

    return list;
}

void list_free(struct list* list) {
    assert(list);
    // 释放指向数据的内存
    free(list->data);
    // 释放指向结构体的内存
    free(list);

    return;
}

int list_count(struct list* list) {
    assert(list);
    assert(list->count >= 0);
    return list->count;
}

void list_clear(struct list* list) {
    assert(list);
    list->count = 0;

    return;
}

int list_isEmpty(struct list* list) {
    assert(list);
    return list->count == 0;
}

int list_contains(struct list* list, int e) {
    assert(list);
    int i;

    for (i = 0; i < list->count; i++) {
        if (list->data[i] == e) return 1;
    }

    return 0;
}

int list_insert(struct list* list, int index, int e) {
    assert(list);
    // 如果 下标不合法,返回 0 表示插入失败
    if (index < 0 || index > list->count) return 0;
    // 如果链表已经存满,则需要增加内存
    if (list->count >= list->size) {
        int* temp = NULL;
        temp = (int*) realloc(list->data, sizeof(int) * (list->size + INCR_SIZE));
        /*
         * -----来自百度百科对 realloc函数 的解释-----
         * realloc原型是extern void *realloc(void *mem_address, unsigned int newsize);
         * 先判断当前的指针指向的内存后面是否有足够的连续空间用于扩展,如果有,扩大mem_address指向的地址,
         * 并且将mem_address返回,如果空间不够,先按照newsize指定的大小分配空间,
         * 将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来mem_address所指内存区域
         * (注意:原来指针是自动释放,不需要使用free),同时返回新分配的内存区域的首地址。
         * 即重新分配存储器块的地址。
         */
        assert(list);
        list->data = temp;
        // 别忘了更新 list 的大小
        list->size += INCR_SIZE;
    }

    // 将index后面的元素往后移,为插入的元素腾出位置
    int i;
    for (i = list->count; i > index; i--) {
        list->data[i] = list->data[i - 1];
    }

    list->data[index] = e;
    list->count++;

    // 返回 1 表示插入成功
    return 1;
}

void list_add(struct list* list, int e) {
    assert(list);
    // 当在末尾添加元素时,数组满了的时候,调整内存大小,同 list_insert()
    if (list->count >= list->size) {
        int* temp = (int*) realloc(list->data, sizeof(int) * (list->size + INCR_SIZE));
        list->data = temp;
        list->size += INCR_SIZE;
    }

    list->data[list->count++] = e;

    return;
}

int list_set(struct list* list, int index, int e) {
    assert(list);
    // 如果index无效,返回 0 表示设置失败
    if (index < 0 || index > list->count) return 0;

    list->data[index] = e;

    return 1;
}

void list_remove(struct list* list, int index, int* e) {
    assert(list);
    // 如果index无效,返回 0 表示删除元素失败
    if (index < 0 || index > list->count) return;

    // 将删除后的元素值保存在 e 中
    *e = list->data[index];

    // 将index后面的元素往前移,填补删除后的空缺
    int i;
    for (i = index; i < list->count - 1; i++) {
        list->data[i] = list->data[i + 1];
    }

    list->count--;

    return;
}

int list_get(struct list* list, int index) {
    assert(list);
    assert(index >= 0 && index < list->count);

    return list->data[index];
}

void list_print(struct list* list) {
    assert(list);
    int i;

    for (i = 0; i < list->count - 1; i++) {
        printf("%d, ", list->data[i]);
    }
    printf("%d\n", list->data[list->count - 1]);

    return;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值