线性表(二):单链表的增删改查及源码

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

//结点结构体定义
typedef struct  link_node {
    int n;//数据域
    struct link_node *next;//指针域:(此时结构体尚未定义完整,不能用 NODE *next; )用该结构体类型定义一个指针,用来指向下一个结点的地址

}NODE;

//创建结点 函数声明
/*
1、定义一个结构体类型指针需分配空间(大小为结构体大小)
2、下一结点初始化为空,数据域初始化
3、返回结点地址
*/

NODE *creat_node(int n) {
    NODE *p = malloc(sizeof(NODE));

    p->next = NULL;
    p->n = n;
    return p;
}


//头插法
/*
1、调用创建结点函数创建一个新结点
2、将头结点的地址赋值给新结点的next指针
3、返回新结点的地址,并将新结点的地址赋值给头结点
*/
void *add(NODE *head,int n) {
    NODE *new = creat_node(n);//创建一个新结点
    new->next = head;//将头结点的地址赋值给新节点的next指针
    return new;//返回新结点的地址
}


//尾插法插入结点
/*
1、先创建一个新的结点(新节点->next指向NULL)
2、寻找最后一个结点
3、将新结点的地址赋值给最后一个结点->next;
*/
void append(NODE *head,int n) {
    NODE *new = creat_node(n);//新建一个待插入结点
    //找最后一个结点
    NODE *end = head;
    while (end->next != NULL)//需要保证end不为空
    {
        end = end->next;
    }
    //循环结束时end为最后一个结点
    end->next = new;

}


//中间插入结点
void insert(NODE *head,int value,int n) {//在链表中的关键值为value的结点后插入一个新结点,新结点的值为n
    NODE *p = creat_node(n);
    NODE *pos = head;
    int flag = 0;

    while (pos!=NULL) {
        if (pos->n == value)
        {
            p->next = pos->next;
            pos->next = p;
            flag = 1;
            break;
        }
        else
        {
            pos = pos->next;
        }
    }
    if (flag == 1)
    {
        printf("插入成功!插入值为%d\n",n);
    }
    else
    {
        printf("插入失败!关键值不存在\n");
    }
}


//删除结点
//分为两种情况
/* 一:要删除的结点是head指针
1、
2、
*/
NODE *delete(NODE *head,int n) {
    if (head->n==n) {
        NODE *p = head;
        head = p->next;
        free(p);
        return head;
    }
    else
    {
        NODE *prev = head;//表示前一结点
        NODE *p = prev->next;//表示下一结点
        //判断
        while (p!= NULL)
        {
            if (p->n == n)
            {
                prev->next = p->next;
                printf("删除成功!删除值为%d\n", p->n);
                free(p);
                break;
            }
            else
            {
                prev = prev->next;
                p = prev->next;
            }
        }
        
    }
}


//查询结点
NODE *query(NODE *head,int n) {
    NODE *p = head;
    while (p!=NULL)
    {
        if (p->n == n)
        {
            printf("已查询到!该关键值为%d,地址为%x\n",p->n,p);//将该值所在结点的16位地址打印出来
            return p;
        }
        else
        {
            p = p->next;
        }
    }
    printf("未查询到该关键值!\n");
    return NULL;
}


//遍历链表
void show_all(NODE *head) {
    NODE *p = head;
    while (p != NULL)
    {
        printf("%d\n",p->n);
        p = p->next;
    }
}


//修改结点
/*两种方法:
一、查找关键值所在结点,再修改值
二、创建一个新结点,用新创建的结点替换要被替换的结点
*/
void modify(NODE *head,int old,int new) {
    NODE *p = head;
    while (p!=NULL)
    {
        if (p->n ==old) {
            p->n = new;
            printf("修改完成!\n");
            return;
        }
        else
        {
            p = p->next;
        }
    }
    printf("修改失败!未查找到要修改的值!\n");
}

//链表销毁
void destroy(NODE *head) {
    NODE *p1;
    NODE *p2;
    p1 = head;
    while (p1!=NULL)
    {
        p2 = p1->next;
        free(p1);
        p1 = p2;
    }

    
    
}


int main(){

    NODE *head = NULL;//head 为一个头指针 初始化赋值为空
    head = creat_node(0);//创建一个结点,并将该结点地址赋值给头指针head
    
    //头插法调用:                    
    //head = add(head,1);//调用头插法函数add,将头指针地址和成员变量做实参传递,返回新节点地址并将新节点地址赋值给头结点
    
    //尾插法调用:
    append(head, 1);
    append(head, 2);
    append(head, 3);
    append(head, 4);

    //调用插入函数
    insert(head, 2, 5);
    insert(head, 6, 5);

    //调用删除函数
    head = delete(head, 0);

    //调用查询函数
    int n;
    scanf("%d",&n);
    NODE *p = query(head, n);

    //调用遍历函数
    show_all(head);

    //调用修改函数
    modify(head,2,6);
    show_all(head);

    //调用销毁函数
    destroy(head);
    return 0;
}

posted @ 2020-08-24 21:56  destiny-2015  阅读(226)  评论(0编辑  收藏  举报