数据结构--单向链表实现功能

一、单向链表概念

1.既然顺序存储中的数据因为挤在一起而导致需要成片移动,那很容易想到的解决方案是将数据离散地存储在不同内存块中,然后在用来指针将它们串起来。这种朴素的思路所形成的链式线性表,就是所谓的链表。
2.顺序表和链表在内存在的基本样态如下图所示:

 二、链表的分类

根据链表中各个节点之间使用指针的个数,以及首尾节点是否相连,可以将链表细分为如下种类:
1.单向链表
2.单向循环链表
3.双向链表
4.双向循环链表

--> 我们这里介绍的就是第一种 <--

三、单向链表功能

1.定义一个结构体

typedef struct node
{
    //存放的数据
    int data;
    //存放下一个节点的指针
    struct node *next;    
}node;   // node == struct node

2.初始化结构体,生成一个新的节点

node *initList(void)
{
    //在堆空间开辟内存
    node *new = malloc(sizeof(node));
    if(new == NULL)
    {
        printf("malloc fail\n");
        return NULL;
    }
    //开辟的空间数据初始化为0
    new->data = 0;
    new->next = NULL;

    return new;
}  

3.头插添加数据

void inset_1(node *head,  node *new)
{
    new->next = head->next;
    head->next = new;
}

4.尾插添加数据

void inset_2(node *head,  node *new)
{
    node *p=NULL;
    for (p = head; p ->next; p=p->next);
    p->next=new;
    new->next=NULL;
}

5.打印数据

void  display(node *head)
{
    int i = 0;
    node *p = NULL;
    for(p = head->next; p != NULL ; p = p->next)
    {
        printf("%d\t", p->data);
    }
    printf("\n");
}

6.查找数据

node *find_data(node  *head, int data)
{
    node *p = NULL;
    for(p = head->next; p != NULL ; p = p->next)
    {
        //判断节点的数据是否等于 查看的数据,如果是,返回节点
        if(p->data == data)
        {
            return p;
        }

    }

    return NULL;
}

7.节点删除 

int  del_node(node *head, int data)
{
    node *del = NULL;
    node *p = NULL;
    del = find_data(head, data);
    if(del == NULL)
    {
        printf("链表当中没有此数据节点\n");
        return -1;
    }
    //遍历查看del 前缀节点
    for(p = head; p != NULL; p = p->next)
    {
        if(p->next == del)
        {
            break;
        }
    }

    //将点解下来
    p->next = del->next;
    del->next = NULL;

    free(del);

    return 0;
}

8.移动数据头插

int move_node(node *head,int data_1,int data_2)
{
    node *p_1 = NULL;
    node *p_2 = NULL;    
    node *q_1 = NULL;
    p_1 = find_data(head, data_1);
    p_2 = find_data(head, data_2);
    if ((p_1 == NULL) || (p_2 == NULL))
    {
        printf("你输入的数据有不存在的现象\n");
        return -1;
    }

    //遍历查看del 前缀节点
    for(q_1 = head; q_1 != NULL; q_1 = q_1->next)
    {
        if(q_1->next == p_1)
        {
            break;
        }
    }
    q_1->next=p_1->next;
    p_1->next=NULL;

    p_1->next=p_2->next;
    p_2->next=p_1;
    return 0;
}

9.单向链表的销毁

void destroy(node *head)
{
    node *p=head->next;
    while(p!=NULL)
    {
        node *pp=p;
        p=p->next;
        free(pp);
    }
    head->next=NULL;
    printf("已经成功摧毁\n");
}

完整代码

#include <stdio.h>
#include <stdlib.h>

typedef struct node
{
    //存放的数据
    int data;
    //存放下一个节点的指针
    struct node *next;    
}node;   // node == struct node
 
//函数声明
node *initList(void);
void inset_1(node *head,  node *new);
void inset_2(node *head,  node *new);
void  display(node *head);
node *find_data(node  *head, int data);
int  del_node(node *head, int data);
int move_node(node *head,int data_1,int data_2);
void destroy(node *head);

int main(void)
{
    //定义局部变量
    char ch;
    int data,data1, ret;
    node *head, *new, *find;

    //生产一个单向链表结构体
    head = initList(); 

    while(1)
    {
        printf("====================请输入你要操作功能====================\n");
        printf("\t\t\ta:头插插入\n");
        printf("\t\t\tb:尾插插入\n");
        printf("\t\t\tc:查找数据\n");
        printf("\t\t\td:删除数据\n");
        printf("\t\t\te:移动数据\n");
        printf("\t\t\tf:摧毁数据\n");
        printf("\t\t\tp:显示数据\n");
    
        //等待获取用户输入
        ch = getchar();

        switch (ch)
        {
            //头插添加数据
            case 'a':
                new = initList();
                printf("请输入要插入的数据:");
                scanf("%d", &new->data);
                inset_1(head,  new);
                break;
            //尾插添加数据
            case 'b':
                new = initList();
                printf("请输入要插入的数据:");
                scanf("%d", &new->data);
                inset_2(head,  new);
                break;
            //查找数据
            case 'c':
                printf("请输入要查找的数据:");
                scanf("%d", &data);
                find = find_data(head, data);
                if(find == NULL)
                {
                    printf("链表当中没有此数据节点\n");
                }
                else
                {
                    printf("链表当中有此数据节点\n它的节点地址:%p\n", find);
                }
                break;
            //节点删除 
            case 'd':
                printf("请输入要删除的数据:");
                scanf("%d", &data);
                ret = del_node(head, data);
                if(ret == 0)
                {
                    printf("节点删除完成\n");
                }

                break;
            //移动数据头插
            case 'e':
                printf("移动到那个数据前面:");
                scanf("%d", &data);
                printf("请输入要移动的数据:");
                scanf("%d", &data1);
                ret = move_node(head, data, data1);
                if(ret == 0)
                {
                    printf("节点移动完成\n");
                }
                break;
            //单向链表的销毁
            case 'f':
                destroy(head);
                break;
            //打印数据
            case 'p':
                display(head);
                break;
            default:
                printf("输入格式错误,请重新输入!\n");
                break;
        }

        while (getchar() != '\n');
    }  

    return 0;
}


//初始化结构体,生成新的一个节点
node *initList(void)
{
    //在堆空间开辟内存
    node *new = malloc(sizeof(node));
    if(new == NULL)
    {
        printf("malloc fail\n");
        return NULL;
    }
    //开辟的空间数据初始化为0
    new->data = 0;
    new->next = NULL;

    return new;
}  

//头插添加数据
void inset_1(node *head,  node *new)
{
    new->next = head->next;
    head->next = new;
}

//尾插添加数据
void inset_2(node *head,  node *new)
{
    node *p=NULL;
    for (p = head; p ->next; p=p->next);
    p->next=new;
    new->next=NULL;
}

//打印数据
void  display(node *head)
{
    int i = 0;
    node *p = NULL;
    for(p = head->next; p != NULL ; p = p->next)
    {
        printf("%d\t", p->data);
    }
    printf("\n");
}

//查找数据,数据存在返回数据所在的节点地址
node *find_data(node  *head, int data)
{
    node *p = NULL;
    for(p = head->next; p != NULL ; p = p->next)
    {
        //判断节点的数据是否等于 查看的数据,如果是,返回节点
        if(p->data == data)
        {
            return p;
        }

    }

    return NULL;
}

//节点删除 
int  del_node(node *head, int data)
{
    node *del = NULL;
    node *p = NULL;
    del = find_data(head, data);
    if(del == NULL)
    {
        printf("链表当中没有此数据节点\n");
        return -1;
    }
    //遍历查看del 前缀节点
    for(p = head; p != NULL; p = p->next)
    {
        if(p->next == del)
        {
            break;
        }
    }

    //将点解下来
    p->next = del->next;
    del->next = NULL;

    free(del);

    return 0;
}

//移动数据头插
int move_node(node *head,int data_1,int data_2)
{
    node *p_1 = NULL;
    node *p_2 = NULL;    
    node *q_1 = NULL;
    p_1 = find_data(head, data_1);
    p_2 = find_data(head, data_2);
    if ((p_1 == NULL) || (p_2 == NULL))
    {
        printf("你输入的数据有不存在的现象\n");
        return -1;
    }

    //遍历查看del 前缀节点
    for(q_1 = head; q_1 != NULL; q_1 = q_1->next)
    {
        if(q_1->next == p_1)
        {
            break;
        }
    }
    q_1->next=p_1->next;
    p_1->next=NULL;

    p_1->next=p_2->next;
    p_2->next=p_1;
    return 0;
}

//单向链表的销毁
void destroy(node *head)
{
    node *p=head->next;
    while(p!=NULL)
    {
        node *pp=p;
        p=p->next;
        free(pp);
    }
    head->next=NULL;
    printf("已经成功摧毁\n");
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值