C单链表操作

函数顺序依次为单链表的创建(头插和尾插法),初始化,判空,遍历,求链表长度,按值查找,按位查找,插入,删除,销毁操作

并且在主函数中举例说了链表的创建,遍历,求长,删除,插入操作;


进阶操作:

c循环链表 http://blog.csdn.net/bestsort/article/details/78715889

http://blog.csdn.net/bestsort/article/details/78715962


#include <stdio.h>

#include <stdlib.h>


typedef int DataType;          //用DataType 替代 int方便修改数据类型
typedef struct Node{
    DataType data;           //数据域
    struct Node *next;      //指针域
}Node;


//建立单链表(尾插法)
//比如说数据1 2 3 4 5
//链表中从头指针开始数据顺序为1 2 3 4 5
//每次从链表末尾插入
Node *CreatTailList(DataType a[],int n){
    Node *s = NULL,*r = NULL;
    Node *first = (Node *)malloc( sizeof(Node));
    r = first;//尾指针初始化
    first -> next = NULL;
    int i = 0;
    for(i;i < n;i++){
        s = (Node*)malloc(sizeof(Node));
        s -> data = a[i];
        r-> next = s;
        r = s;               //将结点S插入到终端结点之后
    }
    r -> next = NULL;       //终端结点指针指向NULL
    return first;
}


//建立单链表(头插法)
//比如说数据1 2 3 4 5
//链表中从头指针开始数据顺序为5 4 3 2 1
//每次从链表头部插入
Node *CreatHeadList(DataType a[],int n){
    Node *s = NULL;
    Node *first = (Node*)malloc(sizeof(Node));
    first -> next= NULL;
    int i = 0;
    for(i;i < n;i++){
        s = (Node*)malloc(sizeof(Node));
        s -> data = a[i];
        s -> next = first -> next;
        first-> next = s;
    }
    return first;


}
//链表初始化
Node *InitList(){
    Node *first = (Node *)malloc(sizeof(Node));
    first->next = NULL;
    return first;
}






//判断空是否为空链表
int Empty(Node *first){
    if(first->next == NULL)
        return 1;
    return 0;
}


//遍历
void PrintList(Node*first){
    Node*p = first -> next;
    while(p != NULL){
        printf("%d ",p->data);
        p = p->next;
    }
}


//求链表长度
int Length(Node*first){
    Node *p = first->next;
    int cnt = 0;
    while(p != NULL){
        cnt++;
        p = p -> next;
    }
    return cnt;
}


//按值查找,查找失败返回0,成功返回数据所在位置
int Locale(Node *first,int x){
    Node *p = first->next;
    int cnt = 1;
    while(p != NULL){
        p = p -> next;
        cnt ++;
        if( p -> data == x)
            return cnt;
    }
    return 0;
}




//按位查找,失败返回0,成功返回指向第x个数据的指针ptr
int Get(Node *first,int x,DataType *ptr){
    Node *p = first->next;
    int cnt = 1;
    while(p != NULL && cnt < x){
        p  = p -> next;
        cnt ++;
    }
    if(p == NULL)
        return 0;
    *ptr = p->data;
    return 1;
}




//插入
int Insert(Node *first,int x,DataType t){ //x 为插入位置,t为要插入的数据
    Node *s = NULL,*p = first;
    int cnt = 0;
    while ( p != NULL && cnt < x - 1){
        p = p -> next;
        cnt ++;
    }
    if(p == NULL ){
        return 0; // 插入位置错误返回0
    }
    s = (Node*)malloc(sizeof(Node));//请求分配空间 .
    s -> data = t;                  //申请一个结点,数据域为x
    s -> next = p -> next;          //将结点S插入到结点P之后
    p -> next = s;
    return 1;
}


//删除某一位置的结点
int Delete(Node *first,int i,DataType *ptr){ //i为要删除的数据,ptr取得删除的值
    Node *p = first,*q = NULL;
    int cnt = 0;
    DataType x;
    while(p != NULL && cnt < i - 1){
        p = p -> next;
        cnt++;
    }
    if(p == NULL || p-> next == NULL){
        return 0;                  //删除失败
    }
    q = p -> next;
    *ptr = q -> data;               //删除失败的值
    p -> next = q -> next;
    free(q);
    return 1;
}


//销毁
void DestroyList(Node *first){
    Node *p = first;
    while (first != NULL){          //依次释放储存空间
        first = first -> next;
        free(p);
        p = first;
    }
}




int main()
{
    Node *first;
    DataType data[] = {1,2,3,4,5};
    int x,n;


    n = sizeof(data)/sizeof(data[0]);//求出数组data中元素个数


    first = CreatTailList(data,n);//尾插


    printf("After Creat,the data is:  ");
    PrintList(first);
    printf("\n");


    if(Delete(first,3,&x)){
        printf("After Delete,the data is:  ");
        PrintList(first);
        printf("   Delete %d",x);
        printf("\n");
    }
    else
        printf("Delete Defult\n");


    if(Insert(first,2,7)){
        printf("After Insert,the data is:  ");
        PrintList(first);
        printf("\n");
    }
    else
        printf("Insert Defult\n");


    printf("the List Length is: %d",Length(first));


    return 0;
}

二.内核链表 内核链表是一种链表,Linux内核中的链表都是用这种形式实现的 1.特性 内核链表是一种双向循环链表,内核链表的节点节点结构中只有指针域 使用内核链表的时候,将内核链表作为一个成员放入到一个结构体中使用 我们在链表中找到内核链表结构的地址,通过这个地址就可以找到外部大结构体的地址,通过大结构体就可以访问其中的成员 优势: 内核链表突破了保存数据的限制,可以用内核链表来保存任何数据(使用一种链表表示各种类型的数据,通用性很强) 内核链表中只有指针域,维护起来更加方便,效率更高 2.使用 内核链表在内核中已经被实现,我们只需要调用其接口直接使用即可 内核链表的实现代码在内核源代码的list.h文件中 3.源代码分析 (1)节点结构: struct list_head { struct list_head *next, *prev;//前置指针 后置指针 }; (2)初始化 #define INIT_LIST_HEAD(ptr) do { \ (ptr)->next = (ptr); (ptr)->prev = (ptr); \ } while (0) (3)插入 //从头部插入 static inline void list_add(struct list_head *new, struct list_head *head)//传入要插入的节点和要插入的链表 { __list_add(new, head, head->next); } //从尾部插入 static inline void list_add_tail(struct list_head *new, struct list_head *head) { __list_add(new, head->prev, head); } (4)通过节点找到外部结构体的地址 //返回外部结构体的地址,第一个参数是节点地址,第二个参数是外部结构体的类型名,第三个参数是节点在外部结构体中的成员名 #define list_entry(ptr, type, member) ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) (5)遍历内核链表 //遍历内核链表 #define list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); \ pos = pos->next) //安全遍历内核链表 #define list_for_each_safe(pos, n, head) \ for (pos = (head)->next, n = pos->next; pos != (head); \ pos = n, n = pos->next) 二.内核链表 内核链表是一种链表,Linux内核中的链表都是用这种形式实现的 1.特性 内核链表是一种双向循环链表,内核链表的节点节点结构中只有指针域 使用内核链表的时候,将内核链表作为一个成员放入到一个结构体中使用 我们在链表中找到内核链表结构的地址,通过这个地址就可以找到外部大结构体的地址,通过大结构体就可以访问其中的成员 优势: 内核链表突破了保存数据的限制,可以用内核链表来保存任何数据(使用一种链表表示各种类型的数据,通用性很强) 内核链表中只有指针域,维护起来更加方便,效率更高 2.使用 内核链表在内核中已经被实现,我们只需要调用其接口直接使用即可 内核链表的实现代码在内核源代码的list.h文件中 3.源代码分析 (1)节点结构: struct list_head { struct list_head *next, *prev;//前置指针 后置指针 }; (2)初始化 #define INIT_LIST_HEAD(ptr) do { \ (ptr)->next = (ptr); (ptr)->prev = (ptr); \ } while (0) (3)插入 //从头部插入 static inline void list_add(struct list_head *new, struct list_head *head)//传入要插入的节点和要插入的链表 { __list_add(new, head, head->next); } //从尾部插入 static inline void list_add_tail(struct list_head *new, struct list_head *head) { __list_add(new, head->prev, head); } (4)通过节点找到外部结构体的地址 //返回外部结构体的地址,第一个参数是节点地址,第二个参数是外部结构体的类型名,第三个参数是节点在外部结构体中的成员名 #define list_entry(ptr, type, member) ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) (5)遍历内核链表 //遍历内核链表 #define list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); \ pos = pos->next) //安全遍历内核链表 #define list_for_each_safe(pos, n, head) \ for (pos = (head)->next, n = pos->next; pos != (head); \ pos = n, n = pos->next) 二.内核链表 内核链表是一种链表,Linux内核中的链表都是用这种形式实现的 1.特性 内核链表是一种双向循环链表,内核链表的节点节点结构中只有指针域 使用内核链表的时候,将内核链表作为一个成员放入到一个结构体中使用 我们在链表中找到内核链表结构的地址,通过这个地址就可以找到外部大结构体的地址,通过大结构体就可以访问其中的成员 优势: 内核链表突破了保存数据的限制,可以用内核链表来保存任何数据(使用一种链表表示各种类型的数据,通用性很强) 内核链表中只有指针域,维护起来更加方便,效率更高 2.使用 内核链表在内核中已经被实现,我们只需要调用其接口直接使用即可 内核链表的实现代码在内核源代码的list.h文件中 3.源代码分析 (1)节点结构: struct list_head { struct list_head *next, *prev;//前置指针 后置指针 }; (2)初始化 #define INIT_LIST_HEAD(ptr) do { \ (ptr)->next = (ptr); (ptr)->prev = (ptr); \ } while (0) (3)插入 //从头部插入 static inline void list_add(struct list_head *new, struct list_head *head)//传入要插入的节点和要插入的链表 { __list_add(new, head, head->next); } //从尾部插入 static inline void list_add_tail(struct list_head *new, struct list_head *head) { __list_add(new, head->prev, head); } (4)通过节点找到外部结构体的地址 //返回外部结构体的地址,第一个参数是节点地址,第二个参数是外部结构体的类型名,第三个参数是节点在外部结构体中的成员名 #define list_entry(ptr, type, member) ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) (5)遍历内核链表 //遍历内核链表 #define list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); \ pos = pos->next) //安全遍历内核链表 #define list_for_each_safe(pos, n, head) \ for (pos = (head)->next, n = pos->next; pos != (head); \ pos = n, n = pos->next) C语言下的单链表,可以增加,删除,查找,销毁节点。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值