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

 更新时间:2022年8月24日 17:18  点击:383 作者:胡安民

前沿

数组长度是固定的,那么在很多时候我们并不知道到底有多少数据需要存储,这时候我么就需要一个可变长度的数组来进行存储,在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;
}

判断数组是否有序

/**
 * 判断数组是否有序
 * @param pCharList
 * @param type  TRUE: 按照ASCII码排序   FALSE: 安装字符长度排序
 * @return
 */
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;
}

二分查询

/**
 * 二分查询,没有找到返回-1  以ASCII码查询
 * @param pCharList
 * @param value
 * @return  找到返回下标,没有找到返回-1
 */
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);
}
/**
 * 根据ASCII码排序,从小到大,或者根据长度排序,从小到大
 * @param pCharList
 * @param type   TRUE就是ASCII码排序, FALSE就是根据长度排序
 */
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语言集合内容请搜索猪先飞以前的文章或继续浏览下面的相关文章希望大家以后多多支持猪先飞!

原文出处:https://blog.csdn.net/weixin_45203607/article/details/126501

[!--infotagslink--]

相关文章

  • C语言实现放烟花的程序

    这篇文章主要为大家详细介绍了C语言实现放烟花的程序,有音乐播放,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-02-23
  • Java8 实现stream将对象集合list中抽取属性集合转化为map或list

    这篇文章主要介绍了Java8 实现stream将对象集合list中抽取属性集合转化为map或list的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-02-05
  • C语言中的字符(char)详细讲解

    本篇文章主要介绍C语言中char的知识,并附有代码实例,以便大家在学习的时候更好的理解,有需要的可以看一下...2020-04-25
  • java8如何用Stream查List对象某属性是否有重复

    这篇文章主要介绍了java8如何用Stream查List对象某属性是否有重复的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-09-11
  • 在java中获取List集合中最大的日期时间操作

    这篇文章主要介绍了在java中获取List集合中最大的日期时间操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-15
  • 详解如何将c语言文件打包成exe可执行程序

    这篇文章主要介绍了详解如何将c语言文件打包成exe可执行程序,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-25
  • C#中list用法实例

    这篇文章主要介绍了C#中list用法,结合实例形式分析了C#中list排序、运算、转换等常见操作技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
  • Java8处理List的双层循环问题

    这篇文章主要介绍了Java8处理List的双层循环问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-19
  • C# List 排序各种用法与比较

    这篇文章主要介绍了C# List 排序各种用法与比较的相关资料,需要的朋友可以参考下...2020-06-25
  • 使用list stream: 任意对象List拼接字符串

    这篇文章主要介绍了使用list stream:任意对象List拼接字符串操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-09-09
  • C语言中free函数的使用详解

    free函数是释放之前某一次malloc函数申请的空间,而且只是释放空间,并不改变指针的值。下面我们就来详细探讨下...2020-04-25
  • C语言中计算正弦的相关函数总结

    这篇文章主要介绍了C语言中计算正弦的相关函数总结,包括正弦和双曲线正弦以及反正弦的函数,需要的朋友可以参考下...2020-04-25
  • 详解C语言中的rename()函数和remove()函数的使用方法

    这篇文章主要介绍了详解C语言中的rename()函数和remove()函数的使用方法,是C语言入门学习中的基础知识,需要的朋友可以参考下...2020-04-25
  • C# List介绍及具体用法

    这篇文章主要介绍了C# List介绍及具体用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-06-25
  • Java List集合返回值去掉中括号('[ ]')的操作

    这篇文章主要介绍了Java List集合返回值去掉中括号('[ ]')的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-29
  • C语言中求和、计算平均值、方差和标准差的实例

    这篇文章主要介绍了C语言中求和、计算平均值、方差和标准差的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-12-10
  • R语言-如何将list转换为向量

    这篇文章主要介绍了R语言-将list转换为向量的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-05-06
  • Python 列表(List)的底层实现原理分析

    这篇文章主要介绍了Python 列表(List)的底层实现原理分析,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-09
  • C语言的基本语法详解

    本篇文章主要讲解C语言 基本语法,这里提供简单的示例和代码来详细讲解C语言的基本语法,开始学习C语言的朋友可以看一下,希望能够给你带来帮助...2021-09-18
  • Java8 使用流抽取List<T>集合中T的某个属性操作

    这篇文章主要介绍了Java8 使用流抽取List<T>集合中T的某个属性操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-02-05