zoukankan      html  css  js  c++  java
  • 数据结构----线性表顺序和链式结构的使用(c)

    PS:在学习数据结构之前,我相信很多博友也都学习过一些语言,比如说java,c语言,c++,web等,我们之前用的一些方法大都是封装好的,就java而言,里面使用了大量的封装好的方法,一些算法也大都写好了,java还有三个特性,封装、继承、多态。当然这里不是讲Java,这里主要是说内部结构,大家都知道数据结构有些东西是分为逻辑结构和物理结构的,物理结构有分为顺序结构和链式结构,有不懂得可以百度百科,这里主要是分享线性表的顺序结构。那么什么是线性表呢,线性表是最基本、最简单、也是最常用的一种数据结构。线性表(linear list)是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列。

    线性表

    • 顺序表
    • 链式表

    1:顺序表分析

    •   结构体创建
    •   初始化顺序表
    •   插入操作
    •   删除操作
    •   查找操作
    •   修改操作

    由于顺序表比较简单,这里解释都在代码中,在外就不在赘述。

    1-1:结构体的创建

    #define ElemType int
    #define MAXSIZE 100     //定义变量不需要分号。
    //创建线性表
    typedef struct {
        ElemType elem[MAXSIZE];
        int length;        //长度
    } SqList;

    1-2:初始化顺序表

    int InitList(SqList &L) {
        // 初始化表,一个空表。
        L.length = 0;
        return 0;
    }

    1-3:操作方法

    /**
     * @descibe 插入元素
     * @param L 线性表
     * @param pos 所在位置(并非角标)
     * @param data 插入元素
     * */
    int ListInsert(SqList &L, int pos, ElemType data) {
        if (pos < 1 || pos > L.length + 1) {
            printf("插入的不合法");
            return -1;
        }
        int i;
        //在插入的同时,i要保证在pos以及pos后方,入1,2,3,4,5当在第3个插入时,须把原有的第三个数据以及以后数据后移一位,空出第三个位置。
        for (i = L.length; i >= pos; i--) {
            L.elem[i] = L.elem[i - 1];
        }
        L.elem[pos - 1] = data;
        L.length++;
        return 0;//
    }
    /**
     * 线性表中删除操作
     * @param L 线性表
     * @param pos 所在位置(并非角标)
     * @param data 插入元素
     * */
    int ListDelete(SqList &L, int pos, int data) {
        if (pos < 1 || pos > L.length) {
            printf("删除角标不合法");
            return -1;
        }
        if (!(L.elem[pos - 1] == data)) {
            printf("没有这个数字");
            return -1;
        }
        int i;
        //在插入的同时,i要保证在pos以及pos后方,入1,2,3,4,5当在第3个插入时,须把原有的第三个数据以及以后数据后移一位,空出第三个位置。
        for (i = pos; i <= L.length; i++) {
            L.elem[i - 1] = L.elem[i];
        }
        L.length--;
        return 0;//返回0表示成功;
    }
    //查找数据
    int queryList(SqList L, int e) {
        //如果小于1证明没有数据,则直接返回。
        if (L.length < 1) {
            printf("表中没有数据");
            return -1;
        }
        for (int i = 0; i < L.length; i++) {
            if (L.elem[i] == e) {
                printf("找到该数据:%d角标为:%d 
    ", L.elem[i], i);
            }
        }
        return 0;
    }
    
    //修改数据
    int xiugai(SqList &L, int pos, int e) {
        if (pos < 1 || pos > L.length) {
            printf("修改角标不合法");
            return -1;
        }
        L.elem[pos - 1] = e;
        return 0;
    
    }
    //打印全部数据
    void PrintF(SqList L) {
        printf("打印表中所有元素
    ");
        int i;
        for (i = 0; i < L.length; i++) {
            printf("%d
    ", L.elem[i]);
        }
    }

    综上所述:线性表和之前的数组类似,很容易理解。在使用的过程记得声明一下方法(函数);

    2:链表分析

    •   结构体创建
    •   初始化顺序表
    •   插入操作
    •   删除操作
    •   查找操作
    •   修改操作

    需要注意的是这里的结构体需要一个指针,前一个结点的指针指向下一个结点,依次类推,最后一个指针指向NULL;

    2-1:结构体创建

    /**
     * @describe 创建一个结构体
     *  SLink *next指针;
     * *SLinkListL 创建一个结构体指针
     * */
    typedef struct SLink {
        int data;
        struct SLink *next;
    } SLink, *SLinkListL;

    2-2:初始化链表

    /**
     * @describe 初始化链表
     * */
    SLinkListL initLinkL() {
        //1:分配一个空间
        SLinkListL sLinkListL = (SLinkListL) malloc(sizeof(SLink));
        //2:判断是否创建成功
        if (!sLinkListL) {
            exit(-1);
        }
        sLinkListL->next = NULL;
        printf("初始化单链表成功
    ");
        return sLinkListL;
    }

    2-3:操作--增删该查

    这里需要注意的是修改这个操作,找p的时候要找到要修改的p,而不是前一个结点,比如说,咱们在第二个位置插入的时候要找到第一个位置作为p,二修改的时候就要找到第二个位置,也就是说pos传值的时候不用减一。

    /**
     * @describe 插入操作
     *
     * @param L 链表类型
     * @param pos 插入位置
     * @param e 插入元素
     * */
    int insertLinkL(SLinkListL &L, int pos, int e) {
        SLinkListL p = L;
        //判断是否符合链表的长度;
        int i = 0;
        //判断长度,寻找要插入的位置(前一位);
        while (p && i < pos-1) {
            p = p->next;
            i++;
        }
        //判断长度是否超过pos
        if (!p || i > pos-1) {
            return 0;
        }
        //为新元素创建结点(分配空间)
        SLinkListL s = (SLinkListL) malloc(sizeof(SLink));
        s->data = e;
        s->next = p->next;
        p->next = s;
        return 1;
    }
    
    /**
     * @describe 删除操作
     * @param L 链表类型
     * @param pos 删除位置
     * @param e 删除存放元素
     * */
    int deleteLinkL(SLinkListL &L, int pos, int *e) {
        SLinkListL p = L;
        //1:判断位置
        int i = 0;
        while (p && i < pos-1) {
            p = p->next;
            i++;
        }
        if (!p || i > pos-1) {
            printf("删除位置不合法
    ");
            return -1;
        }
        //定义一个空的变量,用于存放p的指针,入a1,a2,a3,如果要删除a2,则p指向a1,此时,把a1的next先交给s(暂存,此时代表a2(因为a1的指针是指向a2)),然后用s去取下一个指针(next)就是a3,
        SLinkListL s;//s为了释放掉删除元素的空间
        s = p->next;
        p->next = s->next;
        *e = s->data;//暂存
        free(s);
        printf("删除成功
    ");
        return 0;
    }
    
    /**
     * @describe 查找操作
     * @param L:链表类型
     * @param e:e查找元素
     * */
    int queryLinkL(SLinkListL L, int e) {
        printf("查找元素为:%d",e);
        SLinkListL p = L;
        int i = 1;
        while (p) {
            p = p->next;
            if (p->data == e) {
                printf("找到元素%d
    ", i);
                return 0;
            }
            i++;
        }
        printf("下标不合法/没有找到该数据");
        return -1;
    }
    
    /**
     * @describe 修改操作
     * @param L:链表类型
     * @param i:修改元素的位置
     * @param e:修改元素值
     * */
    int updataLinkL(SLinkListL &L, int pos, int e) {
        printf("修改数据为第:%d 个,值为:%d
    ",pos,e);
        SLinkListL p = L;
        int i = 0;
        while (p && i < pos) {
            p = p->next;
            i++;
        }
        if (!p || i > pos) {
            printf("修改失败--原因:修改的下标越界
    ");
            return -1;
        }
        p->data = e;
        printf("修改成功
    ");
        return 0;
    }
    
    void printLL(SLinkListL L) {
        printf("打印全部数据
    ");
        SLinkListL p = L->next;
        while (p) {
            printf("%d ", p->data);
            p = p->next;
        }
        printf("
    ");
    }

    综上所述:只多了一个指针,一开始看估计还有有看不懂的地方,按照顺序把代码粘贴到你编辑器上,运行起来慢慢看。

  • 相关阅读:
    GMA Round 1 数列求单项
    GMA Round 1 双曲线与面积
    多线程环境中安全使用集合API(含代码)
    使用synchronized获取互斥锁的几点说明
    ThreadPoolExecutor线程池
    线程状态转换
    volatile关键字
    守护线程与线程阻塞的四种情况
    线程挂起,恢复与终止
    线程中断
  • 原文地址:https://www.cnblogs.com/cmusketeer/p/9740789.html
Copyright © 2011-2022 走看看