1)创建结构体,储存节点的数据+指针域; 2)创建指向结构体的指针; 3)用结构体定义单链表; 4)初始化链表头节点:为头节点开辟内存; 5)判断内存是否开辟成功; 6)头节点的指针域置空,使链表长度为0。
typedef struct Node//1 { ElemType data; struct Node *next; }Node; typedef struct Node *LinkList;//2 Status InitList(LinkList& L)//3 { L=(Node*)malloc(sizeof(Node));//4 if(L==NULL)//5 { printf("申请内存空间失败\n"); } L->next=NULL;//6 }
1)生成新结点p和尾结点r; 2)为新节点开辟内存; 3)存入数据域; 4)存入指针域:把原来的尾结点指针域存入,即在末尾插入p; 5)更新r,使其依然为链表尾结点; 6)尾结点指针域置空
void CreateListTail(LinkList *L,int n) { LinkList p,r;//1 while(n--) { p=(Node*)malloc(sizeof(Node));//2 scanf("%d",&p->data);//3 r->next=p;//4 r=p;//5 } r->next=NULL; }
1)结点p储存头结点; 2)判断p是否到表尾,没到就进入以下循环; a.结点q指向p下一个结点; b.释放p结点; c.p指向q结点。 3)头指针置空,相当于初始化链表。
注:不能用p=p->next代替q,∵在free(p)时也释放了指针域,∴p->next不存在。
Statue ClearList(ListLine *L) { ListLine p,q; p=(*L)->next;//1 while(p)//2 { q=p->next;//a free(p);//b p=q;//c } (*L)->next=NULL; }
1)用p指向链表第一个元素; 2)用j遍历链表,直到找到i或p已经到链表结尾,即p=NULL; 3)如果没找到,p指向下一个结点; 4)若退出循环时p为NULL或i元素不存在,则返回ERROR; 5)若找到就把数据存入。
Statue GetElem(LinkList *L,int i,int *e) { int j=1; p=(*L)->next;//1 while(jnext;//3 j++; } if(j>i||!p)//4 { return ERROR; } *e=p->data;//5 return OK; }
在第i位后插入元素e。变成a,e,a+1。
1)遍历链表找到第i位; 2)创立要插入的新节点s; 3)开辟新节点s的内存; 4)s的数据域存入e; 5)连接e与a+1:把a+1的指针域给新结点s; 6)连接a与e:把s给a的指针域。
Statue ListInsert(LinkList *L,int i,ElemType e) { //1 int j=1; LinkList p; p=(*L)->next;//p从头开始找:将链表头结点给p while(p&&jnext; j++; } if(!p||j>i) { return ERROR; } LinkList s;//2 s=(Node*)malloc(sizeof(Node));//3 s->data=e;//4 s->next=p->next;//5 p->next=s;//6 return OK; }
删除i位的元素,并把删除的元素值返回到e中。
1)遍历列表找到i位,注:∵要删除p->next结点,∴p->next不能为NULL; 2)将预删除的结点储存在q内; 3)将p->next赋值为q->next,即进行了p->next=p->next->next操作; 4)把q里的数据——需删除的数据,给e; 5)释放结点q。
Statue ListDelete(LinkList *L,int i,ElemType *e) { //1 int j=1; LinkList p; p=(*L)->next; while(p->next&&jnext; j++; } if(!(p->next)||j>i) { return ERROR; } LinkList q; q=p->next;//2 p->next=q->next;//3 *e=q->data;//4 free(q);//5 return OK; }
void OutPutList(LinkList *L) { LinkList p; p=(*L)->next; while(p) { printf("%d\n",p->data); } }
#include#include #include //用于生成随机数 typedef int Status;//用Status来进行替代int,方便数据类型的修改 typedef int ElemType; #define OK 1; #define ERROR 0; //单链表储存结构 typedef struct Node//定义结构体LNode { ElemType data;//结点数据域 struct Node* next;//结点指针域 }Node; typedef struct Node* LinkList;//LinkList为指向结构体Node的指针类型 //初始化一个空的单链表L Status InitList(LinkList& L) //InitList()顺序表的初始化函数 { L = (Node*)malloc(sizeof(Node)); //申请空间,生成新结点作为L头结点 if (L == NULL) //判断是否有足够的内存空间 { printf("申请内存空间失败\n"); } L->next = NULL; //头结点的指针域置空,初始长度为0 return OK; } //尾插法创建链表 void CreateListTail(LinkList* L, int n)//*L即调用已经存在的线性表L { LinkList p, r;//L:指整个单链表;p:需创建的新节点;r:指向尾结点的变量。 r = *L;//r指向尾部节点 printf("1.输入初始数据\n2.自动生成数据\n");//链表生成类型选择 int a; scanf("%d", &a); if (a == 1) { while (n--) { p = (Node*)malloc(sizeof(Node));//为新结点开辟内存 scanf("%d", &p->data);//读取数据 r->next = p;//在原来的尾结点r后存入 r = p;//更新尾结点 } r->next = NULL;//链表结束 } else if(a==2) { srand(time(0));//初始化随机数种子 r = *L;//r指向链表尾部 while (n--) { p = (Node*)malloc(sizeof(Node));//生成新结点 p->data = rand() % 100 + 1;//随机产生100以内的数 r->next = p;//将新结点添加到表尾 r = p;//更新尾结点:将新结点更新为尾结点 } r->next = NULL;//表示链表结束 } printf("链表创建成功!\n"); } //整表删除,即变成空表 Status ClearList(LinkList* L) { LinkList p, q; p =(*L)->next;//使p指向线性表第一个结点 while (p)//如果p不为NULL { q = p->next;//q指向p的下一个结点,防止释放p后找不到下一个结点 free(p);//释放p结点 p = q;//p指向下一个结点 } (*L)->next = NULL;//使头结点为空,相当于链表初始化时的操作 return OK; } //查找,读取元素,获取第i个元素数据,返回到e Status GetElem(LinkList *L, int i, ElemType* e) { int j=1;//计数,最后一个结点是NULL,不需要遍历∴从1开始计 LinkList p; p=(*L)->next;//p从头结点开始找 //遍历链表,找到第i个元素 while (j next;//指向下一个结点 j++; } if (!p||j>i)//p为空||不存在i结点时 { printf("出错!查找位置在链表之外!\n"); return ERROR; } *e = p->data; return OK; } //在位置i插入元素e,使链表成为 a,e,a+1 Status ListInsert(LinkList* L, int i, ElemType *e) { //先遍历找到第i个结点 int j=1; LinkList p; p = (*L)->next;//p指向链表头结点 if (i == 0)//头结点插入特判 { LinkList s; s = (Node*)malloc(sizeof(Node)); s->data = *e;//存数据域 s->next = (*L)->next;//把原头结点给s的下一个结点 (*L)->next = s;//更新新结点 printf("成功!\n"); return OK; } while (j < i && p) { p=p->next; j++; } if (!p || j > i)//没找到 { printf("出错!插入位置在链表之外!\n"); return ERROR; } //找到位置后插入 LinkList s;//创建要插入的新结点 s= (Node*)malloc(sizeof(Node));//为新节点开辟内存 s->data = *e;//储存数据域 s->next = p->next;//将p后继结点给s的后继,即连接e和a+1 p->next = s;//将s给p的后继,即连接a和e printf("成功!\n"); return OK; } //删除第i个元素,并用e返回其值 Status ListDelete(LinkList* L, int i, ElemType* e) { //遍历找到第i个结点 int j=1; LinkList p; p = (*L)->next; if (i == 1)//若是头结点需特判 { *e = p->data; (*L)->next = p->next;//使链表头结点直接指向下一个 printf("删除元素的值为:%d\n", *e); printf("成功!\n"); return OK; } i--; while (j < i && p->next)//∵需删除p后的结点,∴p->next必须存在 { p = p->next; j++; } if (!(p->next) || i < j) { printf("出错!删除位置在链表之外!\n"); return ERROR; } LinkList q; q = p->next;//将预删除的结点给q p->next = q->next;//p连接需删除结点后的结点,即p->next=p->next->next *e = q->data;//删除结点中的数据给e free(q);//释放删除的结点 printf("删除元素的值为:%d\n", *e); printf("成功!\n"); return OK; } //输出链表 void OutPutList(LinkList* L) { LinkList p; p = (*L)->next; while (p) { printf("%d\n", p->data); p = p->next; } } int main() { Node *L; int n,i,e,q; InitList(L); //目录 printf(" 目录\n"); printf("1.创建链表\n2.查找列表元素\n3.清空链表\n4.插入元素\n5.删除元素\n6.输出链表\n\n"); while (~scanf("%d", &q)) { if (q == 1) { printf("请输入链表数据个数:\n"); scanf("%d", &n); CreateListTail(&L, n); } else if (q == 2) { scanf("%d", &i); GetElem(&L, i, &e); } else if (q == 3) { ClearList(&L); printf("链表已清空!\n"); } else if(q==4) { printf("请输入需插入的位置:\n"); scanf("%d", &i); printf("请输入需插入元素的值:\n"); scanf("%d", &e); ListInsert(&L, i, &e); } else if (q == 5) { printf("请输入需删除的元素位置:\n"); scanf("%d", &i); ListDelete(&L, i, &e); } else if (q == 6) { printf("\n"); OutPutList(&L); } printf(" 目录\n"); printf("1.创建链表\n2.查找列表元素\n3.清空链表\n4.插入元素\n5.删除元素\n6.输出链表\n\n"); } return 0; }
运行截图: