c语言数据结构之单链表

本教程会在以后持续公布c语言数据结构的实现文章,一来重温一下基础知识,二来为正在学习此部分内容的同学提供参考和思路,教程内容均来自于书籍、网友分享和本人思考,侧重代码编写和实现,详细的理论论述还是要翻阅经典的书籍,在此感谢贡献自己智慧的广大编程人员。

今天的主题是单链表,这是一种非常常见的数据结构,隶属于线性表,是一种简单的链式实现方式,文中会实现我们在面试中经常会碰见的【单链表反转】的问题。链表为了实现前驱和后继元素之间的逻辑关系,也就是前后位置和联系,链表中每个节点除了存储数据元素之外,还必须存储其后继节点的存储位置,该存储位置被称为指针域,相应单纯存储数据的位置被称为数据域,而指针域和数据域构成一个链表的基本元素-节点。节点中只有一个指针域,这种链表就被称为单链表。节点部分通过结构体指针和符号常量来实现,结构体指针主要实现链表的节点结构,定义符号常量可以自定义节点数据域存储的数据类型,具体实现:

#include 
#include 
#define ELTYPE int

typedef struct NODE{
    ELTYPE data;
    struct NODE *next;
} *Node;

ELTYPE为在头部定义的数据类型,本例以存储数值型数据为例,next为指向后继节点的指针,Node为指向结构体类型也就是节点类型的指针。有了节点类型,接下来按照一般逻辑需要实现生成链表的功能,代码如下:

Node CreateNode(int n){
    int i;
    Node head,p,q;
    head = p = (Node)malloc(sizeof(struct NODE));
    for(i=0;imalloc(sizeof(struct NODE));
        q->data = 2*i;
        p->next = q;
        p = q; 
    }
    p->next = NULL;
    return head;
}

CreateNode函数形参为链表长度,返回值类型为指向Node类型的指针,指向的节点为链表的头节点。循环体之前声明三个Node类型数据,head,p,q,head为头节点指针域指向链表的第一个节点,p为临时变量,代表循环体中循环创建下一个节点的前驱节点,循环体中每次循环都创建一个新的节点,给数据域赋值和设置当前节点p指向新的节点q,然后q赋值给p,进行下一次循环,q再去连接新的节点q’(下一次循环新创建的节点),在最后一次循环中,链表中最后一个节点q由赋值给了p,所以循环体结束后,p的指针域还未赋值,因为尾节点不再指向任何节点,所以其指针域为空,最后返回头节点,严格说是指向头节点的指针。链表的一个通用功能是链表节点数值的输出,代码实现如下:

void ShowNode(Node head){
    Node curr = head->next;
//  for(;curr;curr = curr->next) printf("%d ",curr->m);
    while(curr != NULL){
        printf("%d",curr->data);
        curr = curr->next;
    }
    printf("\n");
}

链表输出就是出入链表的头节点,顺序打印链表的节点值,上边代码段给出两种循环输出链表节点值的方法。接下来是链表反转:

void ReverseNode(Node head){
    Node p,t,q;
    p = NULL;
    t = head->next;
    q = t->next;
    if(t==NULL || q==NULL) return;
    while(q != NULL){
        t->next = p;
        p = t;
        t = q;
        q = q->next; 
    }
    t->next = p;
    head->next = t;
}

理解这段代码的关键在于弄明白p,t,q的角色,循环之前声明这三个临时变量,可以这样理解:按照顺序p,t,q分别代表每次循环过程中前驱,当前,后继节点,反转的核心就是将原来的前驱->当前->后继 变成 后继->当前->前驱 对应着就是t->next = p;就将当前->后继变成当前->前驱,接着p,t,q向下移动一个节点,进入下一次循环,直到t为尾节点,此时q=NULL,循环结束,手动将尾节点指向倒数第二个节点,设置头节点指向尾节点,这样尾节点就变成链表中的第一个节点,整个链表已经反转完成。检验:

int main(){
    Node head = CreateNode(5);
    ShowNode(head);
    ReverseNode(head);
    ShowNode(head);
    return 0;
}
#运行结果
02468
86420
[Finished in 0.0s]

验证结果与预期一致。

你可能感兴趣的:(c)