链式存储线性表的结构体:
typedef int ElemType; //元素类型 typedef struct Node //链表结构体 { ElemType date; //链表结点数据域 struct Node *next; //链表结点指针域 }Node,*LinkList;
创建链表:
/* 链表的创建操作
使用srand()时,需要引入头文件stdlib.h,即在头文件处添加 #include<stdlib.h>
使用time()时,需要引入头文件time.h,即在头文件处添加 #include<time.h>
使用malloc()时,需要引入头文件malloc.h,即在头文件处添加 #include<malloc.h> */ void CreatList(LinkList *L, int n) { LinkList p,r; int i; srand(time(0)); //初始化随机数种子 *L = (LinkList)malloc(sizeof(Node)); //创建链表空间 //不是表空间,是头结点 2018.8.13/于瑞 r = *L; //r为指向L尾部的指针 for(i = 0; i < n; i++) { p = (Node *)malloc(sizeof(Node)); //创建新结点p //Node *与LinkList等价 2018.8.13/于瑞 p->date = rand() % 100 +1; //为新结点的数据域赋值 r->next = p; //使r指针指向p r = p; //将p结点赋值给r,使r继续为表尾结点 } r->next = NULL; //表尾结点指针域为空 }
链式存储的插入函数:
/* 链表的插入操作 */ Status InsertList(LinkList *L, int i, ElemType e) { int j = 1; //记录当前位置 LinkList p,s; p = *L; //将p指向L的头结点 while(p && j < i) //判断p是否不为空 且 计数器j是否小于插入的位置i { p = p->next; //若是,将指针后移 j++; //计数器加1 } if(!p || j > i) //判断p是否为空 或 计数器j是否大于插入位置i return ERROR; //若是,说明链表为空 或 索引位置有误、 //运行到这,说明已找到需要插入的位置 s = (LinkList)malloc(sizeof(Node)); //创建新结点s s->date = e; //将e值赋值给新结点s的数据域 s->next = p->next; //将p结点的指针域赋值给新结点s的指针域 p->next = s; //将新结点s赋值给p结点的指针域 return OK; //操作成功 }
链式存储的删除函数:
/* 链表的删除操作 */ Status ListDel(LinkList *L, int i, ElemType *e) { int j = 1; //计数器j LinkList p = *L; //创建指针p指向L LinkList q; //用于记录找到的结点信息,,必须有q,否则无法释放 while(p->next && j < i) //判断p是否不为空 且 计数器j是否小于插入的位置i { p = p->next; //若是,将指针后移 j++; //计数器加1 } if(!(p->next) || j > i) //判断p是否为空 或 计数器j是否大于插入位置i return ERROR; //若是,说明链表为空 或 索引位置有误 //运行到这,说明已找到需要插入的位置 q = p->next; //将要删除的结点p->next赋值给q *e = q->date; //将p结点的数据域内容赋值给e p->next = q->next; //将p->next的指针域赋值给p的指针域 free(q); //释放结点q return OK; //操作成功 }
链式存储的索引查找函数:
/* 线性链表的查询操作 */ Status GetElem(LinkList L, int i, ElemType *e) { int j = 1; // LinkList p = L->next; //声明指针p指向L的计数器第一个节点 while(p && j < i) //判断链表是否不为空 并且 计数器j是不是小于所需位置i的大小 { p = p->next; //若是,是p指向下一节点 j++; //是计数器加1 } if (!p || j>i) //判断p是否为空 或 计数器j是不是大于所需位置i的大小 return ERROR; //若是,说明链表为空或位置索引有误 *e = p->date; //若运行此句,说明已找到i位置的元素,将此结点的数据域内容赋值给e return OK; //返回操作成功 }
链式存储的修改函数:
/* 链表的修改操作 */ Status UpdateList(LinkList *L, int i, ElemType e) { LinkList p = (*L) ->next; //使p指向L的第一个结点 int j = 1; //计数器j while(p && j < i) //判断p非空 计数器小于所需位置 { p = p->next; //指针后移 j++; //计数器加1 } if(!p || j > i) //判断p为空 计数器大于所需位置 return ERROR; //返回失败 p->date = e; //使p的数据域为e return OK; //操作成功 }
链式存储的遍历打印函数:
/* 链表的遍历操作 */ void PrintList(LinkList L) { int j = 1; //计数器 LinkList p = L->next; //使p指向L if(!p) printf("表空 "); while(p) { printf("第%d个元素为%d ",j,p->date); p = p->next; j++; } printf(" "); }
整表删除函数:
/* 链表的整表删除操作 */ Status ClearList(LinkList *L) { int j = 1; //计数器1 LinkList p,q; p = (*L)->next; //让p指向L while(p) { q = p->next; //使q指向p free(p); //释放p p = q; //使p指向q } (*L)->next = NULL; //使头指针为空 return OK; //操作成功 }
主函数:
void main() { LinkList L; //创建链表L int i, e; //i为元素位置,e为元素内容 while(true) { printf("请选择对线性链表的操作: "); printf("1.创建 "); printf("2.插入 "); printf("3.删除 "); printf("4.查找 "); printf("5.修改 "); printf("6.输出 "); printf("7.整表删除 "); printf("8.退出 "); int a; scanf("%d", &a); switch(a) { case 1: printf("请输入需要创建元素的个数:"); scanf("%d", &i); if(CreatList(&L, i)) printf("创建成功 "); else printf("创建失败 "); break; case 2: printf("请输入需要插入的位置:"); scanf("%d", &i); printf("请输入需要插入的元素:"); scanf("%d", &e); if(InsertList(&L, i, e)) printf("插入成功 "); else printf("插入失败 "); break; case 3: printf("请输入需要删除的位置:"); scanf("%d", &i); if(ListDel(&L, i, &e)) printf("删除成功 "); else printf("删除失败 "); break; case 4: printf("请输入需要查找的位置:"); scanf("%d", &i); GetElem(L, i, &e); printf("第%d个元素为%d ",i,e); break; case 5: printf("请输入需要修改的位置:"); scanf("%d", &i); printf("请输入新的的元素:"); scanf("%d", &e); if(UpdateList(&L, i, e)) printf("修改成功 "); else printf("修改失败 "); break; case 6: PrintList(L); break; case 7: if(ClearList(&L)) printf("清空成功 "); else printf("清空失败 "); break; case 8: return; default: printf("选择错误 "); break; } } }
经检测,所有代码均可执行!