广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C语言手写集合List的示例代码
  • 652
分享到

C语言手写集合List的示例代码

2024-04-02 19:04:59 652人浏览 薄情痞子
摘要

目录前沿定义结构创建List扩容创建数据节点给集合添加值删除集合内指定的值删除集合内指定下标的值打印集合迭代器查询指定元素的下标(第一个)末尾查询指定元素下标(第一个)判断数组是否有

前沿

数组长度是固定的,那么在很多时候我们并不知道到底有多少数据需要存储,这时候我么就需要一个可变长度的数组来进行存储,在C语言中需要我们自己进行定义,我们称为集合

定义结构

typedef struct charlist {
    char **str;
    int len;
    int capacity;
}CharList;

typedef int boolean;//定义一个布尔类型
#define TRUE 1
#define FALSE 0

创建List

//创建一个空节点, 可以指定容量默认为10
CharList *createCharList(int size) {
    if (size < 10) {
        size = 10;
    }
    //初始化结构体和一个2级指针
    CharList *charList = (CharList *) calloc(1, sizeof(CharList));
    charList->str= (char **) calloc(size, sizeof(char *));
    charList->len = 0;
    charList->capacity = size;
    return charList;
}

扩容

//扩容
static void  dilatation(CharList **pCharList) {
    CharList *charList = *pCharList;
    int capacity1 =charList->capacity;//获取当前节点的容积
    int size = capacity1 + (capacity1 * 0.75);//容积增加
    charList->capacity= size;//更新容积
    char **p1 = (char **) realloc(charList->str,size*sizeof(char *));
    charList->str=p1;
}

创建数据节点

static char *createData(char *data){
    //插入数据
    char *pData = (char *) calloc(strlen(data) + 1,sizeof(char) ); //为啥要+1因为字符串结尾需要有一个空字符
    strcpy(pData,data);
    return pData;
}

给集合添加值

//添加一个值 ,容量不够会自动在原有基础上进行扩容*0.75
void addCharList(CharList **pCharList, char *value) {
    CharList *charList = *pCharList;
    int len1 = charList->len;//获取当前节点的长度
    int capacity1 =charList->capacity;//获取数组的容量
    if (len1 == capacity1) {
        dilatation(pCharList);//扩容
    }
    charList->str[len1] = createData(value);//插入数据
    charList->len++;
}

删除集合内指定的值

void deleteCharList(CharList **pCharList, char *value) {
    CharList *charList = *pCharList;
    int len1 = charList->len;//获取当前节点的长度
    for (int i = 0; i < len1; ++i) {
        if (strcmp(charList->str[i],value)==0) {//找到了
            free(charList->str[i]);//释放内存
            for (int j = i; j < len1 - 1; ++j) {//后面的节点向前移动
                charList->str[j] = charList->str[j + 1];
            }
            charList->len--;
            break;
        }
    }
    
}

删除集合内指定下标的值

//删除集合内指定下标的值
void deleteCharListByIndex(CharList **pCharList, int index) {
    CharList *charList = *pCharList;
    int len1 = charList->len;//获取当前节点的长度
    if (index < 0 || index >= len1) {
        return;
    }
    free(charList->str[index]);//释放内存
    for (int j = index; j < len1 - 1; ++j) {//后面的节点向前移动
        charList->str[j] = charList->str[j + 1];
    }
    charList->len--;
}

打印集合

//打印所有节点
void printCharList(CharList *pCharList) {
    int len1 = pCharList->len;
    for (int i = 0; i < len1; i++) {
        printf("%s\n", pCharList->str[i]);
    }
}

迭代器

先这样简单的使用,如果有需要可以自己定义一套迭代机制

void charListIterator(CharList *pCharList,void (*func)(char *)) {
    int len1 = pCharList->len;
    for (int i = 0; i < len1; i++) {
        func(pCharList->str[i]);
    }
}

查询指定元素的下标(第一个)

//查询指定元素的下标 ,没有找到返回-1
int charListIndexOf(CharList *pCharList, char *value) {
    int len1 =  pCharList->len;
    for (int i = 0; i < len1; i++) {
        if (strcmp(pCharList->str[i],value)==0) {
            return i;
        }
    }
    return -1;
}

末尾查询指定元素下标(第一个)

int charListLastIndexOf(CharList *pCharList, char *value) {
    int len1 =  pCharList->len;
    for (int i = len1 - 1; i >= 0; i--) {
        if (strcmp(pCharList->str[i],value)==0) {
            return i;
        }
    }
    return -1;
}

判断数组是否有序


boolean charListIsSorted(CharList *pCharList,boolean type) {
    int len1 = pCharList->len;
    boolean result; //返回结果
    if(type){//按照ASCII码排序方式进行判断
        //从小到大
        for (int i = 0; i < len1 - 1; i++) {
            if (strcmp(pCharList->str[i],pCharList->str[i + 1])>0) {
                result=FALSE;
                break;
            }
        }
        //从大到小
        for (int i = 0; i < len1 - 1; i++) {
            if (strcmp(pCharList->str[i],pCharList->str[i + 1])<0) {
                result=FALSE;
                break;
            }
        }
    }else{
        //从小到大
        for (int i = 0; i < len1 - 1; i++) {
            if (strlen(pCharList->str[i])>strlen(pCharList->str[i + 1])) {
                result=FALSE;
                break;
            }
        }
        //从大到小
        for (int i = 0; i < len1 - 1; i++) {
            if (strlen(pCharList->str[i])<strlen(pCharList->str[i + 1])) {
                result=FALSE;
                break;
            }
        }
    }

​​​​​​​    return result;
}

二分查询


int charListBinarySearch(CharList *pCharList, char *value) {
    if(!charListIsSorted(pCharList,TRUE)){ //判断是否是排序的数组,如果不是那么我们给排序
        //二分查询需要是有序的数组,所以需要先排序 以ASCII码进行排序
        charListSort(pCharList,1);
    }
    int len1 =  pCharList->len;
    int low = 0;
    int high = len1 - 1;
    while (low <= high) {
        int mid = (low + high) / 2;//中间下标
        if (strcmp(pCharList->str[mid],value)==0) {//找到了
            return mid;
        }
        if (strcmp(pCharList->str[mid],value)>0) {//中间值比查找值大
            high = mid - 1;//向左找
        } else {//比中间值比差值值小
            low = mid + 1;//向右找
        }
    }
    return -1;
}

修改集合指定元素的值

//修改指定元素的值
void charListSet(CharList *pCharList, char *value, int index) {
    int len1 =  pCharList->len;
    if (index < 0 || index >= len1) {
        return;
    }
    free(pCharList->str[index]);
    pCharList->str[index] = createData(value);

}

快速排序

//快速排序 (根据ASCII码排序,从小到大)
static void quickSort(char **str, int left, int right) {
    if (left >= right) {
        return;
    }
    char *p = str[left];
    int i = left;
    int j = right;
    while (i < j) {
        while (i < j && strcmp(str[j],p)>=0) {
            j--;
        }
        str[i] = str[j];
        while (i < j && strcmp(str[i],p)<=0) {
            i++;
        }
        str[j] = str[i];
    }
    str[i] = p;
    quickSort(str, left, i - 1);
    quickSort(str, i + 1, right);
}

​​​​​​​//快速排序(根据长度排序,从小到大)
static void quickSortByLen(char **str, int left, int right) {
    if (left >= right) {
        return;
    }
    char *p = str[left];
    int i = left;
    int j = right;
    while (i < j) {
        while (i < j && strlen(str[j])>=strlen(p)) {
            j--;
        }
        str[i] = str[j];
        while (i < j && strlen(str[i])<=strlen(p)) {
            i++;
        }
        str[j] = str[i];
    }
    str[i] = p;
    quickSortByLen(str, left, i - 1);
    quickSortByLen(str, i + 1, right);
}

void charListSort(CharList *pCharList, boolean type) {
    if(type){
        quickSort(pCharList->str, 0, pCharList->len-1);
    }else{
        quickSortByLen(pCharList->str, 0, pCharList->len-1);
    }
}

集合去重

//去重
void charListDistinct(CharList *pCharList) {
    int len1 = pCharList->len;
    for (int i = 0; i < len1; i++) {
        for (int j = i + 1; j < len1; j++) {
            if (strcmp(pCharList->str[i],pCharList->str[j])==0) {
                free(pCharList->str[j]);//释放内存
                for (int k = j; k < len1 - 1; ++k) {//将后面的内容向前移动
                    pCharList->str[k] = pCharList->str[k + 1];
                }
                //去除结尾的元素
                pCharList->str[len1 - 1]=NULL;
                len1--;
                pCharList->len--;//长度减1
                j--;//重新比较
            }
        }
    }
}

集合复制

//集合复制,返回新集合
CharList *charListCopy(CharList *pCharList) {
    int len1 = pCharList->len;
    CharList *pNewCharList = createCharList(len1);
    for (int i = 0; i < len1; i++) {
        char *p = createData(pCharList->str[i]);
        addCharList(&pNewCharList, p);
    }
    return pNewCharList;
}

集合合并

//集合合并,返回新集合
CharList *charListMerge(CharList *pCharList1, CharList *pCharList2) {
    int len1 = pCharList1->len;
    int len2 = pCharList2->len;
    CharList *pNewCharList = createCharList(len1 + len2);
    for (int i = 0; i < len1; i++) {
        char *p = createData(pCharList1->str[i]);
        addCharList(&pNewCharList, p);
    }
    for (int i = 0; i < len2; i++) {
        char *p = createData(pCharList2->str[i]);
        addCharList(&pNewCharList, p);
    }
    return pNewCharList;
}

集合差集

记A,B是两个集合 ,A集合中不存在B集合的元素,那么A集合就是B集合的差集

//集合差集,返回新集合
CharList *charListDifference(CharList *pCharList1, CharList *pCharList2) {
    int len1 = pCharList1->len;
    int len2 = pCharList2->len;
    CharList *pNewCharList = charListCopy(pCharList1);
    for (int i = 0; i < len2; i++) {
        int index = charListIndexOf(pNewCharList, pCharList2->str[i]);
        if (index != -1) {
            free(pNewCharList->str[index]);//释放内存
            for (int j = index; j < len1 - 1; ++j) {//将后面的内容向前移动
                pNewCharList->str[j] = pNewCharList->str[j + 1];
            }
            //去除结尾的元素
            pNewCharList->str[len1 - 1]=NULL;
            len1--;
            pNewCharList->len--;//长度减1
            i--;//重新比较
        }
    }
    return pNewCharList;
}

集合补集

对于两个给定集合A、B, 如果A集合中不存在B集合元素,那么B集合就是A集合的补集,当然反过来也可以说A集合是B集合的补集

//集合补集,返回新集合
CharList *charListComplement(CharList *pCharList1, CharList *pCharList2) {
    CharList *pCharlist1 = charListDifference(pCharList1, pCharList2);
    CharList *pCharlist2 = charListDifference(pCharList2, pCharList1);
    CharList *pCharlist = charListMerge(pCharlist1, pCharlist2);
    return pCharlist;
}

集合并集

对于两个给定集合A、B,由两个集合所有元素构成的集合,叫做A和B的并集。(需要去重只保留一个)

//集合并集,返回新集合
CharList *charListUNIOn(CharList *pCharList1, CharList *pCharList2) {
    CharList *pCharlist1 = charListDifference(pCharList1, pCharList2);
    CharList *pCharlist2 = charListMerge(pCharlist1, pCharList2);
    return pCharlist2;
}

集合交集

对于两个给定集合A、B,属于A又属于B的所有元素构成的集合,叫做A和B的交集。

//集合交集,返回新集合
CharList *charListIntersection(CharList *pCharList1, CharList *pCharList2) {
    int len2 = pCharList2->len;
    CharList *pNewCharList = createCharList(len2/2);
    for (int i = 0; i < len2; ++i){
        int of = charListIndexOf(pCharList1, pCharList2->str[i]);
        if(of!=-1){
            addCharList(&pNewCharList, pCharList2->str[i]);
        }
    }
    return pNewCharList;
}

销毁集合

// 释放内存
void charListClean(CharList *pCharList) {
    //清理数组内元素
    for (int i = 0; i < pCharList->len; ++i) {
        free(pCharList->str[i]);
    }
    //清除数组
    free(pCharList);
}

到此这篇关于C语言手写集合List的示例代码的文章就介绍到这了,更多相关C语言集合内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: C语言手写集合List的示例代码

本文链接: https://www.lsjlt.com/news/165902.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C语言手写集合List的示例代码
    目录前沿定义结构创建List扩容创建数据节点给集合添加值删除集合内指定的值删除集合内指定下标的值打印集合迭代器查询指定元素的下标(第一个)末尾查询指定元素下标(第一个)判断数组是否有...
    99+
    2022-11-13
  • C语言实现手写红黑树的示例代码
    目录前沿红黑树代码测试前沿 写C的红黑树前建议先看我博客这篇文章Java-红黑树 主要看原理 红黑树代码 #ifndef STUDY_RBTREE_H #define ...
    99+
    2022-11-13
  • C语言实现手写Map(全功能)的示例代码
    目录为啥需要Map结构主流Map结构数组+链表的Map结构hash函数创建Map集合扩容基数扩容Map集合给Map集合添加元素打印Map集合获取Map集合中的指定元素判断键是否存在判...
    99+
    2022-11-13
  • C语言实现手写字符串处理工具的示例代码
    目录头文件实现文件头文件 #ifndef STUDY_STR_UTIL_H #define STUDY_STR_UTIL_H #include "../structure/cha...
    99+
    2022-11-13
  • C语言实现手写Map(数组+链表+红黑树)的示例代码
    目录要求结构红黑树和链表转换策略hash使用要求 需要准备数组集合(List) 数据结构 需要准备单向链表(Linked) 数据结构 需要准备红黑树(Rbtree)数据结构 需要准备...
    99+
    2022-11-13
  • C语言实现栈的示例代码
    目录一、了解栈的结构特点二、具体实现补充 栈的用处一、了解栈的结构特点 栈是一种特殊的线性表,只允许从一端进出数据,称为后进先出,先进后出。 压栈:栈的插入操作叫做进栈/压...
    99+
    2022-11-13
  • C语言实现字符串替换的示例代码怎么写
    本篇文章给大家分享的是有关C语言实现字符串替换的示例代码怎么写,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。 替换,意思就是用另一个字符串str3来替换str1中所有...
    99+
    2023-06-26
  • C语言实现通讯录的示例代码
    目录一、Contact.h文件二、Contact.c文件三、test.c文件一、Contact.h文件 包含函数的声明 #pragma once #define _CRT_SECUR...
    99+
    2022-11-13
    C语言实现通讯录 C语言 通讯录
  • C语言实现大顶堆的示例代码
    目录堆的实现1.堆结构2.堆的种类3.大顶堆代码实现堆的实现 1.堆结构 逻辑结构上类似于 一棵 “树” 2.堆的种类 大顶堆结构: 一种特殊的树:其每个...
    99+
    2022-11-13
  • C语言模拟实现memmove的示例代码
    目录前言例子memmove的模拟实现具体实现步骤总结前言 上一篇我们介绍了memcpy和strcpy的区别,以及memcpy模拟实现,但这两个库函数都有一个缺点,那就是不能自己复制自...
    99+
    2022-12-29
    C语言实现memmove C语言 memmove
  • C语言i++和++i示例代码分析
    这篇文章主要讲解了“C语言i++和++i示例代码分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C语言i++和++i示例代码分析”吧!一看就懂的i++和++i详解前言我相信很多朋友可能之前...
    99+
    2023-07-05
  • C语言责任链模式示例代码
    目录介绍:作用:类比:示例:总结介绍: ​ 责任链模式是一种行为模式,它可以允许你将请求沿着处理者链进行发送,收到请求以后, 每个处理者均可对请求进行处理, 或将其传递给链上的下个处...
    99+
    2022-11-12
  • C#中DataTable和List互转的示例代码
    目录DataTableList1. DataTable转List2. List转DataTableDataTable DataTable 是 C# 中常用的一种数据表格类型,它类似于...
    99+
    2023-05-15
    C# DataTable和List互转 c# DataTable转List
  • C语言实现动态链表的示例代码
    目录结构体定义已经函数声明函数实现创建一个链表判断链表是否为空获得链表中节点的个数在某个特定的位置插入一个元素获得指定下标的节点的元素删除一个节点链表逆序链表的清空链表的销毁链表的遍...
    99+
    2022-11-13
  • C语言制作表白神器的示例代码
    目录程序说明操作说明程序效果完整源码程序说明 这是一个表白神器,可以自己替换上图片识别。 1.程序默认是识别 640×480 尺寸,可以自己调整。 2.也有现成的程序可以...
    99+
    2023-03-07
    C语言制作表白神器 C语言表白神器 C语言表白
  • C语言实现数独程序的示例代码
    目录程序截图简单说明代码实现程序截图 简单说明 随机生成数独的算法见力扣上对应题目的题解,我用的是递归回溯法 力扣原题 先随机放入 11 个数就能生成一个数独然后求数独的解最后...
    99+
    2023-03-03
    C语言实现数独游戏 C语言数独程序 C语言数独
  • C语言示例代码讲解栈与队列
    目录栈栈的定义顺序栈顺序栈的定义顺序栈的初始化顺序栈的入栈顺序栈的出栈取顺序栈的栈顶元素链栈队列队列的定义队列的顺序表达与实现队列顺序存储结构假溢出循环队列循环队列的初始化循环队列的...
    99+
    2022-11-13
  • JavaScript手写代码的示例分析
    小编给大家分享一下JavaScript手写代码的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!1. 实现一个new操作符...
    99+
    2022-10-19
  • C语言模拟实现密码输入的示例代码
    目录引言思路分析代码实现代码分析引言 登录账号时我们要输入密码,密码输入错误时会提示密码错误。有时密码的输入次数会被限制,例如银行卡,当我们3次密码都输入错误时卡会被冻结。下面用C语...
    99+
    2022-11-13
  • C语言手撕一个Hash表(HashTable)实例代码
    目录什么是Hash Table散列函数散列冲突开放寻址法链表法装载因子代码总结什么是Hash Table 散列表用的是数组支持按照下标随机访问数据的特性,所以散列表其实就是数组的一种...
    99+
    2023-03-24
    c语言hash c语言实现哈希表 c语言hash表的实现
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作