数据结构之顺序表、链表

目录

一、数据结构的基本概念

​编辑 二、顺序表与链表

 2.1顺序表创建及算法

 2.1.1顺序表的构建(以学生成绩管理为例)

 2.1.2顺序表的创建 (构建函数)

 2.1.3顺序表内成员的插入(构建函数)

 2.1.4顺序表内成员的删除(构建函数)

 2.1.5顺序表内成员数据修改(构建函数) 

 2.1.6.排序 (构建函数)

 2.1.7顺序表的释放

 2.2有头单链表的创建及算法

 2.2.1链表的构建

  2.1.2链表的创建(构建函数)

 2.1.3链表成员的插入(构建函数) 

2.1.4链表成员的删除(构建函数)

 2.1.5链表的排序(构建函数)

 2.1.6链表的翻转 (构建函数)

 2.1.7链表的遍历及释放(构建函数)


一、数据结构的基本概念

 二、顺序表与链表

 2.1顺序表创建及算法

 2.1.1顺序表的构建(以学生成绩管理为例)

//数据类型
typedef struct stu
{
    char name[20];
    unsigned char age;
    unsigned short sco;
}Stu_t;

//顺序表数据类型
typedef struct list
{
    Stu_t list[N];  //顺序表结构
    unsigned index; //用于记录顺序表使用情况(0~N)
}Seqlist_t;

 2.1.2顺序表的创建 (构建函数)

//创建顺序表
Seqlist_t *create_list(void){
    Seqlist_t *L = (Seqlist_t *)malloc(sizeof(Seqlist_t));    //申请堆区空间
    if (NULL == L)
    {
        puts("创建顺序表失败");
        exit -1;
    }
    memset(L,0,sizeof(Seqlist_t));    //初始化顺序表

    L->index = 0;
    return L;
}

 2.1.3顺序表内成员的插入(构建函数)

顺序表中任意位置插入成员

// 任意位置插入数据
int insert_data(Seqlist_t *L,unsigned pos,Stu_t data){
    //健壮性判断
    if (NULL == L)
    {
        puts("传参为空");
        return -1;
    }
    if (N == L->index)
    {
        puts("表已满 插入失败");
        return -1;
    }
    if (pos > L->index)
    {
        puts("插入位置不合理");
        printf("位置范围为:0<=pos<%d\n",L->index);
        return -1;
    }
    int i = 0;
    for (i = L->index; i > pos; i--)
    {
        L->list[i] = L->list[i-1];    //需要将表中插入位置及之后的数据整体向后移动
    }
    L->list[pos] = data;    //给所需要插入的位置重新赋值
    L->index++;    //顺序表有效成员个数加1
    return 0;
}

 2.1.4顺序表内成员的删除(构建函数)

//任意位置删除数据
int delete_data(Seqlist_t *L,int pos){
    //健壮性判断
    if (NULL == L)
    {
        puts("传参为空");
        return -1;
    }
    if (0 == L->index)
    {
        puts("表空 删除失败");
        return -1;
    }
    if (pos >= L->index)
    {
        puts("删除位置不合理");
        printf("位置范围为:0<=pos<%d\n",L->index-1);
        return -1;
    }
    int i = 0;
    for (i = pos; i < L->index-1; i++)
    {
        L->list[i] = L->list[i+1];    //将所需要删除位置之后的所有成员向前移动
                                        //整体向前覆盖一个位置
    }
    --L->index;    //顺序表有效成员个数减1
    return 0;
}

 2.1.5顺序表内成员数据修改(构建函数) 

//去除重名学生元素
int del_same_data(Seqlist_t *L);

//查找数据(根据姓名)
int find_data(Seqlist_t *L,char *f_name);

//修改数据(根据姓名)
int modify_data(Seqlist_t *L,char *f_name,Stu_t data);


//去除重名学生元素
int del_same_data(Seqlist_t *L){
    //健壮性判断
    if (NULL == L)
    {
        puts("传参为空");
        return -1;
    }
    if (0 == L->index)
    {
        puts("表空 操作失败");
        return -1;
    }
    if (1 == L->index)
    {
        puts("只有一个成员,无重名");
        return -1;
    }
    int i = 0;
    int j = 0;
    int num = L->index;
    for (i = 0; i < L->index; i++)
    {
        for (j = i+1; j < L->index; j++)
        {
            if (0==strcmp(L->list[i].name,L->list[j].name))
            {
                delete_data(L,j);
                j--;
            }
        }
    }
    if (num == L->index)
    {
        puts("无重名");
    }
    return 0;
}

//查找数据(根据姓名)
int find_data(Seqlist_t *L,char *f_name){
    //健壮性判断
    if (NULL == L || NULL == f_name)
    {
        puts("传参为空");
        return -1;
    }
    int i = 0;
    Stu_t temp = L->list[i];
    while (0 != strcmp(f_name,temp.name))
    {
        temp = L->list[++i];
        if (i >= L->index)
        {
            puts("未找到该成员");
            return -1;
        }
    }
    printf("检索成功->姓名为:%-10s 年龄为:%-5d 成绩为:%-5d\n",\
        L->list[i].name,L->list[i].age,L->list[i].sco);
        putchar(10);
    return 0;
}

//修改数据(根据姓名)
int modify_data(Seqlist_t *L,char *f_name,Stu_t data){
    //健壮性判断
    if (NULL == L || NULL == f_name)
    {
        puts("传参为空");
        return -1;
    }else if(0 == L->index)
    {
        puts("表空 操作失败");
        return -1;
    }
    int i = 0;
    Stu_t temp = L->list[i];
    while (0 != strcmp(f_name,temp.name))
    {
        temp = L->list[++i];
        if (i >= L->index)
        {
            puts("未找到该成员");
            return -1;
        }
    }
    printf("检索成功->姓名为:%-10s 年龄为:%-5d 成绩为:%-5d\n",\
        L->list[i].name,L->list[i].age,L->list[i].sco
        );
    L->list[i] = data;
    puts("修改成功!");
    return 0;
}

 2.1.6.排序 (构建函数)

//根据成绩排序
int sort_list(Seqlist_t *L);

//遍历顺序表
int show_list(Seqlist_t *L);

//根据成绩排序
int sort_list(Seqlist_t *L){
    //健壮性判断
    if (NULL == L)
    {
        puts("传参为空");
        return -1;
    }
    if (0 == L->index)
    {
        puts("表空 排序失败");
        return -1;
    }
    if (1 == L->index)
    {
        puts("只有一个成员,无需排序");
        return -1;
    }
    int flag = 0;    //采用标志位的方式降低冒泡排序的时间复杂度
    for (int i = 0; i < L->index-1; i++)
    {
        for (int j = 0; j < L->index-1-i; j++)
        {
            if (L->list[j].sco > L->list[j+1].sco)
            {
                flag = 1;
                Stu_t temp;
                temp = L->list[j];
                L->list[j] = L->list[j+1];
                L->list[j+1] = temp;
            }
        }
        if(0 == flag)
        break;
    }
    return 0;
}


//遍历顺序表
int show_list(Seqlist_t *L){
    //健壮性判断
    if (NULL == L)
    {
        puts("传参为空");
        return -1;
    }
    if (0 == L->index)
    {
        puts("表为空 遍历失败");
        return -1;
    }
    for (int i = 0; i < L->index; i++)
    {
        printf("         姓名为:%-10s 年龄为:%-5d 成绩为:%-5d\n",\
        L->list[i].name,L->list[i].age,L->list[i].sco
        );
    }
    return 0;
}

 2.1.7顺序表的释放

//释放顺序表 
int free_list(Seqlist_t **L){
    //健壮性判断
    if (NULL == L || NULL == *L)
    {
        puts("传参为空");
        return -1;
    }
    free(*L);
    *L = NULL;
    return 0;
} 

 2.2有头单链表的创建及算法

 2.2.1链表的构建

//数据结构体
typedef int data_t; 
//链表结构体(成员结构体)
typedef struct node 
{
    data_t data;
    struct node *next; 
}Node_t;

  2.1.2链表的创建(构建函数)

Node_t *create_list(void){
    Node_t *L = (Node_t *)malloc(sizeof(Node_t));
    if (NULL == L)
    {
        puts("<<创建链表失败/创建结点失败>>");
        exit -1;
    }
    memset(L,0,sizeof(Node_t));
    L->next = NULL;
    return L;
}

 2.1.3链表成员的插入(构建函数) 

单链表的插入方式

//头插法
int head_insert(Node_t *L,data_t data);

//尾插法
int tail_insert(Node_t *L,data_t data);

//任意位置插入
int pos_insert(Node_t *L,unsigned int pos,data_t data);

//头插法
int head_insert(Node_t *L,data_t data){
    //健壮性判断
    if (NULL == L)
    {
        puts("<<传参为空>>");
        return -1;
    }
    int i = 0;
    Node_t *newnode = create_list();    //创建新的节点
    newnode->data = data;    //给新节点赋值
    newnode->next = L->next;    //让新节点指向头节点的下一个节点
    L->next = newnode;    //让头节点指向新节点
   return 0;
}

//尾插法
int tail_insert(Node_t *L,data_t data){
    //健壮性判断
    if (NULL == L)
    {
        puts("<<传参为空>>");
        return -1;
    }
    if (NULL == L->next)
    {
        head_insert(L,data);
        return 0;
    }
    
    Node_t *newnode = create_list();
    if(NULL != newnode->next){
        puts("<<新节点创建失败>>");
        return -1;
    }
    newnode->data = data;    //给新节点赋值
    newnode->next = NULL;
    Node_t *temp = L->next;    //使用临时指针变量保存链表
    while (NULL != temp->next)    //循环找到链表最后一个成员
    {
        temp = temp->next;
    }
    temp->next = newnode;    //让最后一个成员指向新节点
    return 0;
}

//任意位置插入
int pos_insert(Node_t *L,unsigned int pos,data_t data){
    //健壮性判断
    if (NULL == L)
    {
        puts("<<传参为空>>");
        return -1;
    }
    //表空判断
    if (NULL == L->next)
    {
        head_insert(L,data);
        return 0;
    }
    Node_t *newnode = create_list();    //给新节点分配空间
    newnode->data = data;    //给新节点赋值
    Node_t *temp = L;    //创建临时变量保存链表
    //插入位置合理性判断
    for (int i = 0; i < pos-1; i++)
    {
        temp = temp->next;
        if (NULL == temp)
        {
            puts("<<插入位置错误>>");
            free(newnode);    //如果插入位置不合理需要释放之前给新节点申请的空间
            return -1;
        }
    }
    //插入操作
    newnode->next = temp->next;
    temp->next = newnode;
    return 0;
}

2.1.4链表成员的删除(构建函数)

//头部删除
int head_delet(Node_t *L);

//尾部删除
int tail_delet(Node_t *L);

//任意位置删除
int pos_dleet(Node_t *L,unsigned int pos);

//头部删除
int head_delet(Node_t *L){
    //健壮性判断
    if (NULL == L)
    {
        puts("<<传参为空>>");
        return -1;
    }
    if (NULL == L->next)
    {
        puts("<<表为空 删除失败>>");
        return -1;
    }
    Node_t *del = L->next;
    L->next = del->next;
    free(del);
    del = NULL;
    return 0;
}

//尾部删除
int tail_delet(Node_t *L){
    //健壮性判断
    if (NULL == L)
    {
        puts("<<传参为空>>");
        return -1;
    }
    //表空判断
    if (NULL == L->next)
    {
        puts("<<表为空 删除失败>>");
        return -1;
    }
    //成员唯一判断
    //如果不判断,当成员唯一时,链表尾的查找会越界
    if (NULL == L->next->next)
    {
        head_delet(L);
        return 0;
    }
    Node_t *temp = L; 
    while (NULL != temp->next->next)    //注意越界
    {
        temp = temp->next;
    }
    Node_t *del = temp->next;
    temp->next = NULL;
    free(del);
    return 0;
}

//任意位置删除
int pos_dleet(Node_t *L,unsigned int pos){
    //健壮性判断
    if (NULL == L)
    {
        puts("<<传参为空>>");
        return -1;
    }
    //表空判断
    if (NULL == L->next)
    {
        puts("<<表空,删除失败>>");
        return -1;
    }
    //成员唯一判断
    if (NULL == L->next->next)
    {
        head_delet(L);
        return 0;
    }
    Node_t *delnode = create_list();
    Node_t *temp = L;
    //删除位置合理性判断
    for (int i = 0; i < pos-1; i++)
    {
        temp = temp->next;
        if (NULL == temp->next)
        {
            puts("<<删除位置错误>>");
            free(delnode);
            return -1;
        }
    }
    delnode = temp->next;
    temp->next = delnode->next;
    free(delnode);
    return 0;
}

 2.1.5链表的排序(构建函数)

//链表排序
int sort_list(Node_t *L){
    //健壮性判断
    if (NULL == L)
    {
        puts("<<传参为空>>");
        return -1;
    }
    //表空判断
    if (NULL == L->next)
    {
        puts("<<表空,删除失败>>");
        return -1;
    }
    //成员唯一判断
    if (NULL == L->next->next)
    {
        head_delet(L);
        return 0;
    }
    //通过创建两个指针 先后遍历链表进行数据比较
    Node_t *first = L->next;
    Node_t *second = first->next;
    data_t temp = 0;
    while (NULL != first->next)    //冒泡排序的思想
    {
        while (NULL != second)
        {
            if (first->data <= second->data)    //判断为真 交换数据
            {
                temp = first->data;
                first->data = second->data;
                second->data = temp;
            }
            second = second->next;    //第二个指针向后走
        }
        first = first->next;    //数据交换成功 两个指针同时向后走
        second = first->next;
    }
    return 0;
}

 2.1.6链表的翻转 (构建函数)

//链表的反转
int reversal_list(Node_t *L){
    //健壮性判断
    if (NULL == L)
    {
        puts("<<传参为空>>");
        return -1;
    }
    //表空判断
    if (NULL == L->next)
    {
        puts("<<表空,反转失败>>");
        return -1;
    }
    //成员唯一判断
    if (NULL == L->next->next)
    {
        puts("<<只有一个成员无需反转>>");
        return 0;
    }

    //方法一
    Node_t *new_L = L->next->next;
    L->next->next = NULL;
    Node_t *temp = new_L;
    while (NULL != new_L)
    {
        temp = temp->next;
        new_L->next = L->next;
        L->next = new_L;
        new_L = temp;
    }
    //方法二
    // Node_t *temp = L->next;
    // Node_t *new_L = L;
    // new_L->next = NULL;
    // while (NULL != temp)
    // {
    //     head_insert(new_L,temp->data);
    //     temp = temp->next;
    // }
    return 0;
}

 2.1.7链表的遍历及释放(构建函数)

//遍历链表
int show_list(Node_t *L);

//释放链表
int free_list(Node_t **L);

//遍历链表
int show_list(Node_t *L){
    //健壮性判断
    if (NULL == L)
    {
        puts("<<传参为空>>");
        return -1;
    }
    Node_t *temp = L->next;
    while (NULL!= temp)
    {
        printf("%d\n",temp->data);
        temp = temp->next;
    }
}

//释放链表
int free_list(Node_t **L){
    //健壮性判断
    if (NULL == L || NULL == *L)
    {
        puts("<<传参为空>>");
        return -1;
    }
    //方法一
    Node_t *temp = *L;
    Node_t *fr_temp = NULL;
    while (NULL != temp->next)
    {
        fr_temp = temp->next;
        temp->next = fr_temp->next;
        free(fr_temp);
        fr_temp = NULL;
    }
    free(temp);
    temp = NULL;
    *L = NULL;
    //方法二
    // Node_t *temp = *L;
    // while (NULL!=(*L))
    // {
    //     temp = (*L)->next;
    //     printf("%d 节点将会被释放\n",(*L)->data);
    //     free(*L);
    //     *L = temp;
    // }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Little_Star0/article/details/128959111