有头节点的单链表操作
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXSIZE 20 #define ERROR 0 #define OK 1 #define FALSE 0 #define TRUE 1 typedef int Status; typedef int ElemType; //定义链表结构 typedef struct Node{ ElemType data; struct Node *Next; }Node; typedef struct Node* LinkList; //初始化链表 void ListCreate(LinkList *head){ *head=(LinkList)malloc(sizeof(Node)); (*head)->Next=NULL; }
解析初始化链表时为什么形参使用二级指针:
因为我们封装的这个初始化链表的函数是有参无返回值的函数,大家都知道函数在执行完后会释放掉函数内部的所有变量的内存空间,为了修改链表的内容得以保存,则在主函数当中定义一个二级指针,则这个二级指针是在主函数当中开辟的内存空间,将它的地址传入被调函数,通过*(间接访问)去改变指针内部的值。因为这个二级指针的内存是在主函数中开辟的,只要主函数没有结束就不会消失,故调用函数之后,完成了值的改变!后面的插入删除都是用二级指针,同理!
//查找链表中的元素并返回值到变量e中 Status GetElem(LinkList L,int i,ElemType *e){ LinkList p; int j=1; p=L->Next; while(p&&j<i){ p=p->Next; j++; } if(j>i||!p) return ERROR; *e=p->data; return OK; }
解析为什么获取链表中的元素时形参是一级指针而不是二级指针:
首先,我们要封装的这个函数功能是找到链表中指定位置的元素并返回这个元素的值到变量e中!由函数所要实现的功能可知,并没有修改链表中的内容,因此只需要传入一级指针可以遍历链表就足够了!
//插入节点 Status ListInsert(LinkList *L,int i,ElemType e){ int j=1; LinkList p=*L,a; while(p&&j<i){ p=p->Next; j++; } if(!p||j>i) return ERROR; a=(LinkList)malloc(sizeof(Node)); a->data=e; a->Next=p->Next; p->Next=a; return OK; } //删除节点 Status ListDelete(LinkList *L,int i,ElemType *e){ LinkList p=*L; int j=1; while(j<i&&p->Next){ p=p->Next; j++; } if(j>i||!(p->Next)) return ERROR; *e=p->Next->data; p->Next=p->Next->Next; return OK; }
//清空整个链表 Status ClearList(LinkList *L){ LinkList p,q; q=(*L)->Next; while(p){ p=q->Next; free(q); q=p; } (*L)->Next=NULL; return OK; }