栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C语言实现可增加长度的线性表(示例实现交并补差)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C语言实现可增加长度的线性表(示例实现交并补差)

        总所周知,C语言的数组是不可增加长度的,这就导致很多时候不能采取随机存储结构数组。这时很多人想到了链表,我们可以申请空间存放数据然后插入表中,确实可行,但是随机存储结构的优点可以在“O(1)”的时间内存就不存在了,得到的是一个可以很方便插入删除的链表。

 

        但这时问题就来了,如果我并不需要频繁的做插入删除操作呢?链表的缺点是需要一个指针指向下一个节点,这浪费了很多的空间。

        上图是顺序存储结构示意图,可以很容易得到,存放n个数据需要n*存放数据的数据类型的长度。比如int为一个字长,如果你是三十二位操作系统就是4个字节,六十四位就是8个字节。

 

        上图可以很直观的看出,存放n个数据时它需要的空间是远远多于顺序存储结构的,相当于需要2倍的顺序存储结构需要的空间。

        回归正题,可不可以实现动态的数组呢?答案是可以的。

#define init_list_length 26
#define num 10
struct arrayList{
    char *element;
    int length;
    int maxLength;
};
typedef struct arrayList *List;
typedef struct arrayList Node;

         需要一个结构体结构体,结构体中三个元素的作用分别是element相当于指向数组头节点的指针,数组的当前有效长度,和当前最大长度。详细说明一下什么是指向头节点的指针,对于c语言申请一个int类型的数组需要这样的语句int   a[5];a就是指向头节点的指针,有些同学这时会有些疑问,不是数组吗怎么又变成指针了?你们可以尝试一下下面的代码。

    int a[2]={2,3};
    int *b;
    b = a;
    printf("%dn",*b);
    printf("%dn",*(b+1));

         运行结果是2,3(ps这里没考虑换行)。

        解决了一个问题,但是还有一个问题,它怎么变成动态的了。话不多说关门,放代码。

void dilation(List list){//扩容
    list->maxLength+=num;
    realloc(list->element,list->maxLength);
}

        每当你要插入或输入一个新的元素时,当前元素长度就加一了,length==maxLength就代表着已经到顶了,这时就要用上这个realloc语句。先将maxLength+=一个事先定义好的常数值,然后重新申请空间。realloc语句的好处是,会把原来的数据按序填入到新申请的数据空间中,这样就可以在保留原数据的基础上,进行了扩容的操作。

        虽然这里没有实现JAVA中ArrayList的可以自由控制存储类型,但是要实现也不会太过复杂,根据不同的数据类型申请不同大小的空间就是了。JAVA中ArrayList见下图。

public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
        ArrayList arrayList = new ArrayList<>();
        ArrayList   arrayList1 = new ArrayList<>();
    }

 交并补差的实现:

        

1.需求分析

  1. 集合的元素限定为小写字母字符(‘a’..’z’),集合输入的形式为一个以“回车符”为结束标志的字符串,串中字符顺序不限,且允许出现重复字符或非法字符,程序应能自动滤去。输出的运算结果字符串中将不含重复字符和非法字符。
  2. 演示程序以用户和计算机的对话方式执行,即在计算机终端上显示“提示信息”后,由用户在键盘上输入演示程序中规定的运算命令,相应的输入数据(滤去输入中的非法字符)和运算结果显示在其后。
  3. 程序执行的命令应包括:① 构造集合1;② 构造集合2;③ 求并集;④求补集;⑤求差集:⑥求交集。
  4. 测试数据为任意键盘上的输入。

例如feubvaufo2foHKUNEUWF52631应该滤去所有大写字母、数字和重复的元素,剩下feubvao。能正确的求出选择的操作如交并补差并正确的输出。

2. 程序结构流程图:

3.调用分析:

        主函数调用menu菜单,菜单中判断输入是否合法,不合法会提示重新输入直到合法,检测输入的数字执行对应的操作。

        选择有一到七七个整数。

        输入一和二时会调用输入函数,可以往集合中输入元素,调用插入函数,每次输入一个元素判断合法性然后插入到顺序表的最后一位,插入函数调用扩容函数,若长度等于最大长度时,会新申请空间。二选项与一相同。如下图3.1、3.2。

        当你输入三时,调用求并集的函数,传入三个集合,分别时集合一集合二集合三,通过对集合一和集合二求并集得到集合三,调用了定位函数,即使用遍历来判断集合中是否存在的函数。然后在调用插入函数,把重复元素剔除后插入表三。调用输出表中元素的函数,依次输出表中的元素。然后释放表三中的元素,做一次重新申请的操作。如下图3.3。

        四到七调用的函数整体与三相同,不过多赘述。

图3.1

图3.2

图3.3

        交并补差差别很大,但是对于代码来说,其实差别不大。比如交集和并集,前者是要新的集合保留求交集的集合的共同元素,并集是把俩个集合中的重复元素删除然后变成一个新的集合(ps集合的元素唯一性)。

        而对于补集就是把全集中的求补集的集合(比如说A)中的元素删去得到了集合A的补集。差集也差不多,把A集合中的属于B集合的元素删去,或把B集合中属于A集合的元素删去。

        讲来讲去,都是找重复、删除之类的操作,所以考虑到重用性,我们完全可以把这些写成函数,然后直接调用就完事了。

找重复元素的代码:

Status LocateEle(List list,Element element){//判断表中是否有重复元素
    for(int i=0;ilength;i++){
        if(list->element[i]==element){
            return Ok;
        }
    }
    return Error;
}

        list是传入一个集合,element是传入一个自定义类型的元素(typedef char Element)。Ok与Error是宏定义#define,相当于JAVA中Boolean类型的True和False。找到了就返回Ok,没找到则返回Error。

        删除的代码其实逻辑上是删除,代码操作上来说可以变成不插入这个元素。因为会创建一个新的集合来存放,不符合条件的直接不存放入这个集合就行了。

        需要注意每次操作完,需要清空A和B经过操作得到的集合。对应的函数是freeC(),意为释放C集合。

void freeC(List c){
    c->length = 0;
    c->element = (Element *) malloc(sizeof (Element)*c->maxLength);
}

总代码:

#include "stdio.h"
#include "stdlib.h"
#define init_list_length 26
#define num 10
#define Ok 1
#define Error 0;

struct arrayList{
    char *element;
    int length;
    int maxLength;
};
typedef int Status;
typedef struct arrayList *List;
typedef struct arrayList Node;
typedef char Element;

Status LocateEle(List list,Element element);//定位
void insertEle(List list,int n,Element element);//插入,n插入位置,ele插入元素
void dilation(List list);//扩容
void printArrayList(List list);//打印
void initArrayList(List list);//初始化
void freeArr(List list,List list1);//终止程序
void unionArr(List list,List list1,List list2);//并集
void complementArr(List list,List list2);//补集
void intersectionArr(List list,List list1,List list2);//交集
void differenceArr(List list,List list1,List list2);//差集
void inputEle(List list);//输入
void DeleteEle(List list,Element element);//删除指定元素
void DeleteEle1(List list,int n);//删除下标为n的元素

void DeleteEle(List list,Element element){//删除元素
    for(int i=0;ilength;i++){
        if(list->element[i]==element){
            for(int j=i;jlength-1;j++){//全部前移一位
                list->element[j] = list->element[j+1];
                list->length--;//表长减一
            }
            break;
        }
    }
}

void freeC(List c){
    c->length = 0;
    c->element = (Element *) malloc(sizeof (Element)*c->maxLength);
}

void DestroyArr(List list){
    if(list->length==0){
        free(list->element);
    }
}

void dilation(List list){//扩容
    list->maxLength+=num;
    realloc(list->element,list->length);
}

Status LocateEle(List list,Element element){//判断表中是否有重复元素
    for(int i=0;ilength;i++){
        if(list->element[i]==element){
            return Ok;
        }
    }
    return Error;
}

void insertEle(List list,int n,Element element){//插入的位置n,插入的元素element
    if(n>list->length){//插入位置应该小于或等于当前长度,当插入位置等于当前长度时,即插入最后一个位置

    }else if(n==list->length){//当插入最后一个的时候,长度加一
        if(list->length==list->maxLength){
            dilation(list);
        }
        list->element[n] = element;
        list->length++;
    }else{
        list->element[n] = element;
    }
}

void inputEle(List list){
    Element c='0';
    printf("请输入集合中的元素n");
    for(int i=0;c!='n';){
        c = getchar();
        if(c>='a'&&c<='z'&&!LocateEle(list,c)){//LocateEle有该元素返回Ok无元素返回Error
            insertEle(list,i,c);
            i++;
        }
    }
}

void initArrayList(List list){//初始化
    list->length = 0;
    list->maxLength = init_list_length;
    list->element = (Element *) malloc(sizeof (Element)*init_list_length);
}

void unionArr(List list,List list1,List list2){//求并集
    printf("集合一:");
    printArrayList(list);
    printf("集合二:");
    printArrayList(list1);
    for(int i=0,j=0,k=0;j!=list1->length||i!=list->length;){
        if(i!=list->length&&!LocateEle(list2,list->element[i])){//如果并集的中没有这个元素就插入这个元素
            insertEle(list2,k++,list->element[i]);
        }
        if(j!=list1->length&&!LocateEle(list2,list1->element[j])){
            insertEle(list2,k++,list1->element[j]);
        }
        if(i!=list->length){
            i++;
        }
        if(j!=list1->length){
            j++;
        }
    }
    printf("集合一和集合二的并集是:");
    printArrayList(list2);
    freeC(list2);
}

void complementArr(List list,List list1){//求补集
    char a='a';
    for(int i=0,k=0;ilength;i++){
        if(!LocateEle(list1,list->element[i])){
            insertEle(list2,k++,list->element[i]);
        }
    }
    printf("集合一:");
    printArrayList(list);
    printf("集合二:");
    printArrayList(list1);
    printf("集合一对集合二的差:");
    printArrayList(list2);
    freeC(list2);
}

void intersectionArr(List list,List list1,List list2){//求交集
    for(int i=0,k=0;ilength;i++){
        if(LocateEle(list1,list->element[i])){
            insertEle(list2,k++,list->element[i]);
        }
    }
    printf("集合一:");
    printArrayList(list);
    printf("集合二:");
    printArrayList(list1);
    printf("集合一和集合二的交集:");
    printArrayList(list2);
    freeC(list2);
}

void freeArr(List list,List list1){//?????
    printf("欢迎再次使用。n");
    free(list);
    free(list1);
    exit(0);
}

void printArrayList(List list){
    for(int i=0;ilength;i++){
        printf("%c ",list->element[i]);
    }
    printf("n");
}

int menu(){
    char a,b[200];
    printf("------输入对应编号选择操作------n");
    printf("------1.初始化集合一------n");
    printf("------2.初始化集合二------n");
    printf("------3.求并集-----------n");
    printf("------4.求补集-----------n");
    printf("------5.求差集-----------n");
    printf("------6.求交集-----------n");
    printf("------7.退出-------------n");
    while(1){
        printf("请输入操作编号n");
        scanf("%c",&a);
        gets(b);
        if(b[0]!=''){
            a = '8';
        }
        if(a>'0'&&a<='7') break;
        printf("error!n");
    }
    return (int )(a-'0');
}

int main(){
    int n,i=0;
    List a,b,c;
    a = (List) malloc(sizeof (Node));
    b = (List) malloc(sizeof (Node));
    c = (List) malloc(sizeof (Node));
    initArrayList(a);
    initArrayList(b);
    initArrayList(c);
    while(i<100){
        n = menu();
        switch (n) {
            case 1:
                inputEle(a);
                printf("集合一:");
                printArrayList(a);
                break;
            case 2:
                inputEle(b);
                printf("集合二:");
                printArrayList(b);
                break;
            case 3:
                unionArr(a,b,c);
                break;
            case 4:
                complementArr(a,c);
                complementArr(b,c);
                break;
            case 5:
                differenceArr(a,b,c);
                differenceArr(b,a,c);
                break;
            case 6:
                intersectionArr(a,b,c);
                break;
            case 7:
                freeArr(a,b);
                break;
        }
        i++;
  }
    return 0;
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/346844.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号