c语言链表

目录

c语言暂时更新完毕

链表实现

链表改进及其函数

补充知识volatile关键字


链表实现

#include <stdio.h>
#include "node.h"
#include <stdlib.h>
//node头文件内容:
//typedef struct _node{
//    int value;
//    struct _node *next;
//}Node;
typedef struct test{
    int a;
}Test;
void add(Node*head,int number);
int main(int argc,char const *argv[]) {
    int number;
    Node * head=NULL;
    do {
        scanf("%d",&number);
        if ((number!=-1)){
            //如果输入的不是-1则申请一个结点空间
           add(head,number);//将添加过程抽取成一个函数add
        }
    }while (number!=-1);
    return 0;
}
void add(Node *head,int number){
    //这里复习一下malloc,它返回的是一个指针,是指向一块内存的指针,指针p能够p->value就不难理解了
    Node *p=(Node*)malloc(sizeof(Node));
    //给value赋值
    p->value=number;
    //因为这是新节点,新结点的的下一个结点肯定是NULL
    p->next=NULL;
    //定义一个尾指针,从头开始遍历找到最后一个结点
    Node *last=head;
    if (last){//因为在链表最初始化时,last=head=null
        while (last->next){//向后搜索找到尾,这里可以用一个一直指向尾的指针tail代替这里不展开了
            last=last->next;
        }
        //找到后,把新建立的结点p给尾指针,也就是放到链表尾
        last->next=p;
    } else{
        head = p;//注意了这里需要修改head,但是这个head是局部变量,与外面的head无关
        /*
         * 几种解决办法
         * 1、将head声明为全局变量,有害不推荐
         * 2、函数返回一个Node *head 但是对之后用这个函数的人有要求,必须用head来接收
         * 3、我们传入head的指针进去,形参当然也是head指针的指针Node** pHead,函数里面的head全部写为*pHead
         * 4、建立一个结构:List,里面有Node *head,所有的head都被List list代替当然初始化也是list.head=NULL,add函数传入&list
         * 这里使用方案4进行改进,这样做的好处是我们定义了一个可以扩展的类型
         * */
    }
}

链表改进及其函数

#include <stdio.h>
#include "node.h"
#include <stdlib.h>
//node头文件内容:
//typedef struct _node{
//    int value;
//    struct _node *next;
//}Node;
typedef struct list{
    Node *head;
    //Node *tail  这里尾指针不展开
}List;
void add(List *pList,int number);
void print(List *list);
void search(List *list,int number);
void delete(List *list,int number);
void clearList(List *list);
int main(int argc,char const *argv[]) {
    int number;
//    Node * head=NULL;
//改进
    List list;
    list.head=NULL;
    do {
        scanf("%d",&number);
        if ((number!=-1)){
            //如果输入的不是-1则申请一个结点空间
            add(&list,number);//将添加过程抽取成一个函数add
        }
    }while (number!=-1);
    //链表遍历
    print(&list);
    //搜索链表
    scanf("%d",&number);
    search(&list,number);
    //删除
    scanf("%d",&number);
    delete(&list,number);
    print(&list);
    //链表的清除
    clearList(&list);
    print(&list);
    return 0;
}
void add(List *pList,int number){
    //这里复习一下malloc,它返回的是一个指针,是指向一块内存的指针,指针p能够p->value就不难理解了
    Node *p=(Node*)malloc(sizeof(Node));
    //给value赋值
    p->value=number;
    //因为这是新节点,新结点的的下一个结点肯定是NULL
    p->next=NULL;
    //定义一个尾指针,从头开始遍历找到最后一个结点
    Node *last=pList->head;
    if (last){//因为在链表最初始化时,last=head=null
        while (last->next){//向后搜索找到尾,这里可以用一个一直指向尾的指针tail代替这里不展开了
            last=last->next;
        }
        //找到后,把新建立的结点p给尾指针,也就是放到链表尾
        last->next=p;
    } else{
        pList->head = p;//注意了这里需要修改head,但是这个head是局部变量,与外面的head无关
        /*
         * 几种解决办法
         * 1、将head声明为全局变量,有害不推荐
         * 2、函数返回一个Node *head 但是对之后用这个函数的人有要求,必须用head来接收
         * 3、我们传入head的指针进去,形参当然也是head指针的指针Node** pHead,函数里面的head全部写为*pHead
         * 4、建立一个结构:List,里面有Node *head,所有的head都被List list代替当然初始化也是list.head=NULL,add函数传入&list
         * 这里使用方案4进行改进
         * */
    }
}
void print(List *list){
    Node *p;
    //for也可以写为这样:for (list->head;list->head; list->head=list->head->next),从而去掉Node *p
    for (p = list->head;p; p=p->next) {
        printf("%d\t",p->value);
    }
}
void search(List *list,int number){
    Node *p;
    int isFound=0;
    for (p=list->head;p; p=p->next) {
        if (p->value==number) {
            printf("找到了!\n");
            isFound = 1;
            break;
        }
    }
    if (!isFound){
        printf("没找到!\n");
    }
}
void delete(List *list,int number){
    Node *p;
    Node *q;//现在光有一个p不行了得有一个q等于p前面一个结点
    for (q = NULL,p = list->head;p; q=p,p=p->next) {
        if (p->value == number){
            if (q){
                q->next=p->next;//注意这里q可能出现可以出现null,需要边界检测
                //在->左边的指针都得做边界检测
            } else{
                list->head=p->next;
            }
            free(p);
            break;
        }
    }
}
void clearList(List *list){
    Node *p;
    Node *q;//用q来指向当前结点的下一个结点
    for (p=list->head;p;p=q) {
        q=p->next;
        free(p);
    }
    printf("清楚成功!\n");
}


补充知识volatile关键字

volatile关键字用来修饰变量时,就告诉编译器该变量是随时变化的,让编译器不做寄存器缓冲优化,直接从存储器读取。

原因:当一个变量频繁变化且有寄存器存储被读写,如果有其他程序修改这个变量就会出现不一致现象

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值