动态链表的增删改查,打印销毁等基本操作及代码模块化(完整C语言代码!)

首先介绍一些链表的基本知识,然后通过程序实现链表操作的基本功能,增删改查,打印等等操作,并模块化来深化这部分知识点。

链表基础知识

1、由一张内存图展开

(1)链表有一个“头指针”变量,如果不提供“头指针”,整个链表都无法访问;
(2)链表的每个元素成为“结点”,每个结点包括数据和下一个结点的地址。末尾的结点地址部分为NULL(空地址);
(3)链表中个元素在内存中的地址可以是不连续的;

2、链表的建立
(1)静态链表:所有结点在程序中定义的,不是临时开辟的,也不能用完后释放;
(2)动态链表:在程序执行过程中从无到有地建立起一个链表,即一个一个地开辟结点和输入各结点数据,并建立起前后相链的关系。

3、链表的基本操作
写这个代码的时候,中间因为一个while写成了if真是最后测试一直错误,真是醉了!!!奉上完整代码。有错的地方请指正~测试下来是没错的。

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

typedef int Datatype;   //如果存其他类型的数据可以在此处直接修改

typedef struct node {
    Datatype data;
    struct node *next;
}Node;

//创建结点
Node* creatNode(Datatype data) {
    Node* p = NULL;
    p = (Node*)malloc(sizeof(Datatype));    //申请内存
    if (p == NULL) {    //安全检查
        return NULL;
    }
    p->data = data;     //赋值
    p->next = NULL;
    return p;
}
//打印链表
void printList(Node* head) {
    Node* p = head;
    if (head == NULL) {
        return;
    }
    while(p != NULL) {
        printf("%d\n",p->data);
        p = p->next;
    }
    return;
}
//在一个结点后插入新结点
int insertNodeBehind(Node* p,Node* pnew) {
    if (p == NULL || pnew == NULL) {
        return -1;
    }
    if (p->next != NULL) {
        pnew->next = p->next;
        p->next = pnew;
    }
    else {
        p->next = pnew;
    }
/*其实此处直接写
    pnew->next = p->next;
    p->next = pnew;
 就可以了,因为若p->next = NULL则pnew->next = NULL*/
    return 0;  
}
//结点后插入一个数据
int insertDataBehind(Node *p,Datatype data) { Node* pnew = NULL; if (p == NULL) { return -1; }
    pnew = creatNode(data);
    insertNodeBehind(p,pnew);
    return 0;
}
//返回最后末尾结点的地址
Node* findListTail(Node* phead) {
    if (phead == NULL) {
        return NULL;
    }
    while (phead->next != NULL) {
        phead = phead->next;
    }
    return phead;
}
//插入数据到链表的末尾,**是因为可能会涉及修改头指针,在没有结点的情况下
int listInsertDataAtTail(Node** phead,Datatype data) {
    Node *p = NULL;
    if (phead == NULL) {
        return -1;
    }
    if (*phead == NULL) {
        *phead = creatNode(data);
        return 0;
    }
    p = findListTail(*phead);
    insertDataBehind(p,data);
    return 0;
}

//删除后一个结点
int deleteNodeBehind(Node* p) {
    Node* temp  = NULL;
    if (p == NULL) {
        return -1;
    }
    if (p->next == NULL) {
        return 1;
    }
    temp = p->next;
    p->next = p->next->next;
    free(temp);
    return 0;
}
//返回数据为data的结点的地址
Node* findNode(Node* head,Datatype data) {
    Node* p = NULL;
    if (head == NULL) {
        return NULL;
    }
    p = head;
    while (p->data != data) {
        if (p->next != NULL) {
            p = p->next;
        }
        else {
            return NULL;    //没找到该数据为data的结点
        }
    }
    return p;
}
//改数据
int listChangeData(Node* head,Datatype oldData,Datatype newData) {
    Node* p = NULL;
    if (head == NULL) {
        return -1;
    }
    p = findNode(head, oldData);
    p->data = newData;
    return 0;
}
//返回数据为data的结点的前一个结点的地址
Node* findPrevNode(Node *head,Datatype data) {
    Node* p = NULL;
    if (head == NULL) {
        return NULL;
    }
    p = head;
    while (p->next != NULL) {
        if (p->next->data == data) {
            return p;
        }
        else {
            p = p->next;
        }
    }
    return NULL;
}
//删除链表中第一个数据为data的结点
int listDeleteData(Node** phead,Datatype data) { Node* p = NULL; Node* temp = NULL; if (phead == NULL || *phead == NULL) { return -1; }
    if ((*phead)->data == data) { temp = (*phead); (*phead) = (*phead)->next; free(temp); return 0; }
    p = findPrevNode(*phead, data);
    deleteNodeBehind(p);
    free(temp);
    return 0;
}
//销毁链表
int listDestroy(Node **phead) {
    if (phead == NULL || (*phead) == NULL) {
        return 0;
    }
    while ((*phead)->next != NULL) { deleteNodeBehind(*phead); } (*phead) = NULL; free(*phead); //不知道此处有没有错误! return 0; }
int main(int argc, const char * argv[]) {
// 创建结点,查尾,增加结点
    Node* p = NULL;
    listInsertDataAtTail(&p, 1); //调用了creatNode,findListTail,insertNodeBehind
    printList(p);

    listInsertDataAtTail(&p, 2);
    listInsertDataAtTail(&p, 3);
    listInsertDataAtTail(&p, 4);
    listInsertDataAtTail(&p, 5);

    printf("已有节点:1-2-3-4-5\n");
    printList(p);

// 删除
// printf("删除1后面结点\n");
// listDeleteData(&p, 1);
// listDeleteData(&p, 3);
// printList(p);

// 修改
    printf("修改2为20000\n");
    listChangeData(p, 2, 20000);
    printList(p);

    listDestroy(&p);
    printList(p);
    return 0;
}

output:

1
已有节点:1-2-3-4-5
1
2
3
4
5
修改2为20000
1
20000
3
4
5

终于好了~休息了,休息了~晚安,虽然看客还不多,不过慢慢来,会坚持写下去的,最近这样写下来收获还是很大的,毕竟要给别人看(虽然没人哈哈哈哈),有些知识点也补漏了一些~继续加油!
等有人了,多提提意见各位大牛~谢啦

你可能感兴趣的:(链表,C语言,增删改查,ios开发基础,代码模块化)