-seventy-
Welcome to my blog space.

认识线性表

/*
    1.线性表:
       ---数据结构中最简单的一种存储结构,专门用于存储逻辑关系为"一对一"的数据 

    2.线性表存储结构,可细分为"顺序存储结构"和"链式存储结构",即如下所示
        线性表:
            1.顺序表(顺序存储结构)
            2.链表(链式存储结构)

    3.存储的类型要求
        使用线性表存储的数据,如同向数组中存储数据那样要求数据类型必须一致
        线性表存储的数据,要么全部都是整型,要么全部都是字符串
        一半整型,另一半是字符串的一组数据无法使用线性表存储

    4.前驱与后继:
        一组数据中的每个个体被称为“数据元素”(简称为“元素”)
            1.前驱
                某一元素的左侧相邻元素称为“直接前驱”,位于此元素左侧的所有元素都统称为“前驱元素”
            2.后继
                某一元素的后侧相邻元素称为“直接后继”,位于此元素右侧的所有元素都统称为“后继元素”
*/

认识顺序表

/*
    顺序表:
    ---它对数据的物理存储结构有要求
       顺序表存储数据时,会提前申请一块足够大小的内存
       然后将数据依次存储起来
       存储时做到数据元素之间不留一丝缝隙(即:连续)

*/

初始化顺序表

# include <stdio.h>
# include <malloc.h>


// 定义表格类型
typedef struct
{
    int* head;        // 指针,存储申请的内存首地址
    int length;        // 当前数据个数
    int size;        // 元素个数(最大容量)

}Table;


// 生成表格的函数
Table tableFunc()
{
    Table t;        // 定义一个变量 t ,其类型为“表格类型”
    // t 表格的初始化
    t.size = 5;                                // 表格最大容量(元素个数) = 5
    t.length = 0;                            // 表格当前数据个数(元素个数)= 0
    t.head = (int*)calloc(t.size,sizeof(int));    // 为表格开辟内存,并把内存首地址赋值给 t.head
    // 注意!上面的申请内存操作可能会出现申请失败的情况,返回值为 NULL
    if (!NULL)
    {
        printf("申请内存失败,程序终止!\n");
        exit(0);
    }
    
    return t;    // 返回 t 表格
}


int main()
{
    Table myTab = tableFunc();

    printf("%d \n", myTab.size);
    printf("%d \n", myTab.length);
    printf("%X \n", myTab.head);    // 内存地址一般用 %X 十六进制展示


    return 0;
}

顺序表的增、删、查、改

/*
    顺序表元素:
    1.查(可以使用查找算法:  1.顺序查找    2.二分法查找)
    2.改
    3.增(增加到前面、中间、后面)------知识点补充:扩容函数:realloc(需要扩容的指针"*p",扩容后总的大小)
    4.删
*/

认识链表

/*
    1.链表:
        1.链表是通过指针,将不连续的内存连接起来,实现链式存储的

        2.内存实际上是不同时机申请的,地址不一定连续,但是可以通过指针联系起来

        3.链表是数据结构中线性表的一种,其中的每个元素实际上是一个“单独的结构体变量”,
        所有变量都“通过”每个元素中的“指针”连接在一起。

        4.以结构体为节点,将一个结构体看成“数据域”和“指针域”两个部分,
        “数据域”用于“存储数据”,“指针域”用于“连接下一个节点”,链表中每个结构体对象叫做节点,
        其中,第一个数据节点,叫做链表的“首元结点”。

        5.如果第一个节点不用于存储数据,只用于代表链表的起始点,则这个结点称为链表的“头结点”。
        

    2.链表特点:
        1.没有固定长度
        2.可以快速的插入和删除链表中的节点

    
    3.链表分很多种,单链表是其中最简单的一种(如下图)

*/

 单链表

/*
    <单链表>

    1.链表节点一般是自定义的结构体类型

    2.结构体一般包含两部分:数据、指针
        数据:当前节点里面需要的数据
        指针:指向下一个节点(最后一个节点置空 为“尾节点”) 

*/

创建单链表 [Go]

 源代码如下

// main.c

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

int main()
{
    Node* pList=CreateList(5);    // 创建一个可以存储5个东西的链表,并将返回值“地址”赋值给变量 pList
    showList(pList);    // 展示链表
    return 0;
}
// myList.c

# include <stdio.h>
# include "myList.h"
# include <stdlib.h>    // 申请内存时候要用

/*
创建链表
参    数:长度
返回值:头指针
*/
Node* CreateList(int length)
{
    // 判断长度
    if (length <= 0)
    {
        printf("Length Error!\n");
        return NULL;
    }

    // 开始创建链表

    // 1.创建头指针和尾指针
    Node *phead, *ptail;
    phead = ptail = NULL;

    // 2.申请内存:头结点
    phead = (Node*)malloc(sizeof(Node));

    // 3.处理异常情况
    if (NULL == phead)
    {
        perror("malloc failed!");
        exit(EXIT_FAILURE);
    }

    // 4.给头结点初值
    phead->pnext = NULL;    // 等价于 (*phead).pnext = NULL;
    phead->num = 0;

    // 5.尾指针
    ptail = phead;

    // 6.向头结点后面添加结点
    Node* p;
    DataType n;
    for (int i = 0; i < length; i++)
    {
        // 6.1 申请一个结点,检测,给值
         p= (Node*)malloc(sizeof(Node));
         if (NULL == p)
         {
             perror("malloc failed!");
             exit(EXIT_FAILURE);
         }
         p->pnext = NULL;
         printf("请输入数值>>>");
         scanf("%d", &n);
         p->num = n;

         // 6.2 将新申请的结点添加到链表中
         ptail->pnext = p;
         ptail = p;        // 更新尾结点
    }


    return phead;    // 9.返回头指针
}



/*
遍历链表
参    数:头指针
返回值:空
*/
void showList(const Node* const p)
{
    // 从首元结点开始遍历,而不是头结点(因为我们不使用头结点去存储值)
    Node* temp = p->pnext;
    if (NULL == temp)
    {
        printf("List is NULL!\n");
        return ;
    }
    printf("\n*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n");
    printf("当前链表数据:\n");
    while (temp)
    {
        printf("%-5d", temp->num);
        temp = temp->pnext;
    }
    printf("\n*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n");
}
// myList.h

#ifndef _MYLIST_    // 防止重复定义
#define    _MYLIST_

typedef int DataType;    // 可以灵活改变数据类型

struct node
{
    struct node* pnext;        // 指针域
    DataType num;            // 数据域
};

typedef struct node Node;    // 给结构体类型取别名



/*
    创建链表
    参    数:长度
    返回值:头指针
*/
Node* CreateList(int length);



/*
    遍历链表
    参    数:头指针
    返回值:空
*/
void showList(const Node* const p);



#endif    // _MYLIST_ 定义结束

单链表的查、改、增、删

/*
    单链表的查、改、增、删
        1.查:确定查找方式,查找之后一般会返回“结点首地址”或者返回 NULL
        2.改:找到目标元素,直接修改该元素的值
        3.增:一定注意不能丢失指针指向
        4.删:记得释放内存

        [Go]
*/

 

posted on 2023-07-16 10:05  -seventy-  阅读(9)  评论(0)    收藏  举报