C语言实现一个单链表

来源:互联网 发布:amd cpu优化 编辑:程序博客网 时间:2024/05/16 12:59

虽然不是原创的,但是我觉得很有必要将这些数据结构实现一遍,正如我所说的对错不重要,关键在于成长。

代码编写之前先了解一下单链表的特点

┌───┬───┐
│data │next │
└───┴───┘
data域--存放结点值的数据域
next域--存放结点的直接后继的地址(位置)的指针域(链域)。

这里我觉得应该说明一下数组和链表的区别:
二者都属于一种数据结构从逻辑结构来看1. 数组必须事先定义固定的长度(元素个数),不能适应数据动态地增减的情况。当数据增加时,可能超出原先定义的元素个数;   当数据减少时,造成内存浪费;数组可以根据下标直接存取。2. 链表动态地进行存储分配,可以适应数据动态地增减的情况,且可以方便地插入、删除数据项。  (数组中插入、删除数据项时,需要移动其它数据项,非常繁琐)链表必须根据next指针找到下一个元素。从内存存储来看1. (静态)数组从栈中分配空间, 对于程序员方便快速,但是自由度小2. 链表从堆中分配空间, 自由度大但是申请管理比较麻烦 
还有几种主要区别我觉得应该说明
    1.数组是在内存中开辟一段连续的空间来存储数据,而链表是靠指针来连接多块不连续的的空间,在逻辑上形成一片连续的空间来存储数据。
    2.数组定位比较快,可以利用下标定位,而链表只能通过遍历来查找元素

    3.链表插入删除比较方便,因为可以动态开辟内存,而数组一开始就确定好了数组的长度,所以插入或删除比较麻烦。


下面正式进入实现

list.h

#ifndef LIST_H#define LIST_Htypedef int T;typedef struct node *PNode;typedef struct node{//数据T data;//指向下个数据的指针PNode next;}Node;//定义一个PNode型的位置指针typedef PNode Position;//定义一个PNode型的链表typedef PNode List;//构造空链表List InitEmpty(List L);//判断链表是否为空int IsEmpty(List L); //判断位置P的节点是否为尾节点int IsLast(Position P);//查找链表中数据为X的第一个节点Position Find(T X, List L);//删除链表中数据为X的第一个节点void Delete(T X, List L);//查找链表中数据为X的第一个节点的上一个节点Position FindBefore(T X, List L);//查找链表中数据为X的第一个节点的下一个节点Position FindNext(T X, List L);//在链表的P位置插入数据为X的节点void Insert(T X, Position P);//删除链表中除头节点外的所有节点void DeleteList(List L);//获取头结点在链表中的位置Position GetHeader(List L);//获取链表中第一个数据节点的位置Position GetFirstData(List L);//获取P位置的后续节点的位置Position Advance(Position P);//获取P位置的数据项T GetData(Position P);#endif

list.c
#include "list.h"#include <malloc.h>#include <stdlib.h>
#include <assert.h>//构造空链表List InitEmpty(List L){L=(PNode)malloc(sizeof(Node));L->next=NULL;return L;}//判断链表是否为空int IsEmpty(List L){return L->next==NULL;}//判断位置P的节点是否为尾节点int IsLast(Position P){return P->next==NULL;}//查找链表中数据为X的第一个节点Position Find(T X, List L){Position p;//P指向第一块内存                p=L->next;//如果P不为空,并且数据不为X,P指向下一块内存        while(p!=NULL&&p->data!=X){p=p->next;}return p;}//删除链表中数据为X的第一个节点void Delete(T X, List L){Position p, temp;//首先找到这个要删除的节点,并记录他的NEXT指针,因为如果不记录先释放的话,会找不到他指向的下一块内存        temp=Find(X, L);//找到他的上一个节点        p=FindBefore(X, L);if(!IsLast(p)){//他上一个节点的NEXT指针现在指向了他的下个节点,这样就把当前节点删除了。                p->next=temp->next;free(temp);}}//查找链表中数据为X的第一个节点的上一个节点Position FindBefore(T X, List L){Position p;p=L;//P为链表首地址,遍历链表,如果它的下个节点不为空,并且下个节点的数据不为X//设置P为它的下个节点,直到满足条件时,返回P         while(p->next!=NULL&&p->next->data!=X)p=p->next;return p;}//查找链表中数据为X的第一个节点的下一个节点Position FindNext(T X, List L){return Find(X, L)->next;}//在链表的P位置插入数据为X的节点void Insert(T X, Position P){Position temp;//开辟一块长度为Node型变量的内存,返回值为PNode型        temp=malloc(sizeof(Node));if(temp==NULL)exit(0);//设置数据为X,NEXT指针指向P位置的下一个节点,此时P和temp都指向P的下个节点//要形成链表,所以把P的NEXT指针指向节点temp         temp->data=X;temp->next=P->next;P->next=temp;}//删除链表中除头节点外的所有节点void DeleteList(List L){Position p, temp;//第二个节点p=L->next;//NEXT指针置空L->next=NULL;if(p!=NULL){//记录第三个节点temp=p->next;//释放第二个节点free(p);//p重新赋予第三个节点p=temp;}}//获取头结点在链表中的位置Position GetHeader(List L){return L;}//获取链表中第一个节点的位置//区分第一个节点和头节点,头节点中只存了第一个节点的地址Position GetFirstData(List L){if(L->next!=NULL)return L->next;
<span style="white-space:pre"></span>return NULL;}//获取P位置的下一个节点的位置Position Advance(Position P){if(P!=NULL)return P->next;return NULL;}//获取P位置的数据项T GetData(Position P){assert(P!=NULL);return P->data;}

test.c

#include "list.h"#include <stdio.h>#include <stdlib.h>int main(){List list=NULL;Position p; int i;list = InitEmpty(list);printf("已生成空链表list\n");if(IsEmpty(list))printf("经检验list是个空链表\n");p = list;for(i=0;i<5;i++){Insert(i*i,p);p = Advance(p);printf("已插入的值为%d新节点\n", GetData(p));}p = FindNext(9, list);printf("数据项为9的节点后继的数据项值为%d\n", GetData(p));p = FindBefore(9, list);printf("数据项为9的节点前驱的数据项值为%d\n", GetData(p));Delete(9, list);p = list;for(i=0;i<4;i++){p=Advance(p);printf("删除数据项为9的节点剩下的节点值为%d\n", GetData(p));}DeleteList(list);printf("已删除链表list的所有数据节点\n");if(IsEmpty(list))printf("经检验list是个空链表\n");}


输出结果:

已生成空链表list经检验list是个空链表已插入的值为0新节点已插入的值为1新节点已插入的值为4新节点已插入的值为9新节点已插入的值为16新节点数据项为9的节点后继的数据项值为16数据项为9的节点前驱的数据项值为4删除数据项为9的节点剩下的节点值为0删除数据项为9的节点剩下的节点值为1删除数据项为9的节点剩下的节点值为4删除数据项为9的节点剩下的节点值为16已删除链表list的所有数据节点经检验list是个空链表

这样单链表就构建完成,记录下来,温故而知新


0 0
原创粉丝点击