第2章课本算法实现 SinglyLinkedList
时间:2019-01-23
本文章向大家介绍第2章课本算法实现 SinglyLinkedList,主要包括第2章课本算法实现 SinglyLinkedList使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
/*******************************************
* 文件夹: ▲02 线性表\04 SinglyLinkedList *
* 文件名: SinglyLinkedList.h *
* 内 容: 单链表相关操作列表 *
*******************************************/
#ifndef SINGLYLINKEDLIST_H
#define SINGLYLINKEDLIST_H
#include <stdio.h>
#include <stdlib.h> //提供malloc、realloc、free、exit原型
#include "../../▲01 绪论/Status.h" //**▲01 绪论**//
#include "../../▲01 绪论/Scanf.c" //**▲01 绪论**//
/* 单链表类型定义 */
#ifndef BANKQUEUING_H /*后续的模拟银行排队算法中,此类型需要重新定义*/
typedef int LElemType_L;
/* 单链表结构体 */
typedef struct LNode
{
LElemType_L data;
struct LNode* next;
}LNode;
typedef LNode* LinkList; //指向单链表结点的指针
#endif
/* 单链表(带头结点)函数列表 */
// (01)初始化单链表L
Status InitList_L(LinkList *L);
//(02)置空单链表L,头结点保留
Status ClearList_L(LinkList L);
//(03)销毁单链表L,连同通结点一起销毁
void DestroyList_L(LinkList *L);
//(04)判断单链表L是否为空
Status ListEmpty_L(LinkList L);
//(05)返回单链表L元素个数
int ListLength_L(LinkList L);
//(06)算法2.8:用e接收单链表L中第i个元素
Status GetElem_L(LinkList L, int i, LElemType_L *e);
//(07)返回单链表L中第一个与e满足Compare关系的元素位序
int LocateElem_L(LinkList L, LElemType_L e, Status(Compare)(LElemType_L, LElemType_L));
//(08)用pre_e接收cur_e的前驱
Status PriorElem_L(LinkList L, LElemType_L cur_e, LElemType_L *pre_e);
//(09)用next_e接收cur_e的后继
Status NextElem_L(LinkList L, LElemType_L cur_e, LElemType_L *next_e);
//(10)算法2.9:在单链表L第i个位置之前插入e
Status ListInsert_L(LinkList L, int i, LElemType_L e);
//(11)算法2.10:删除单链表L第i个位置的值,并用e接收
Status ListDelete_L(LinkList L, int i, LElemType_L *e);
//(12)用Visit函数访问单链表L
Status ListTraverse_L(LinkList L, void(Visit)(LElemType_L));
//(13)算法2.11:头插法建立单链表L(逆序输入)
Status CreateList_HL(FILE *fp, LinkList *L, int n);
//(14)尾插法建立单链表L(顺序输入)
Status CreateList_TL(FILE *fp, LinkList *L, int n);
#endif
/*******************************************
* 文件夹: ▲02 线性表\04 SinglyLinkedList *
* 文件名: SinglyLinkedList.c *
* 算 法: 2.8、2.9、2.10、2.11 *
*******************************************/
#ifndef SINGLYLINKEDLIST_C
#define SINGLYLINKEDLIST_C
#include "SinglyLinkedList.h" //**▲02 线性表**//
//(01)初始化单链表L
Status InitList_L(LinkList *L)
{
(*L) = (LinkList)malloc(sizeof(LNode));
if(!(*L))
exit(OVERFLOW);
(*L)->next = NULL;
return OK;
}
//(02)置空单链表L,头结点保留
Status ClearList_L(LinkList L) //保留头结点
{
LinkList pre, p;
if(!L)
return ERROR;
pre = L->next;
while(pre)
{
p = pre->next;
free(pre);
pre = p;
}
L->next = NULL;
return OK;
}
//(03)销毁单链表L,连同通结点一起销毁
void DestroyList_L(LinkList *L) //销毁所有结点
{
LinkList p = *L;
while(p)
{
p = (*L)->next;
free(*L);
(*L) = p;
}
}
//(04)判断单链表L是否为空
Status ListEmpty_L(LinkList L)
{
if(L!=NULL && L->next==NULL) //链表存在且只有头结点
return TRUE;
else
return FALSE;
}
//(05)返回单链表L元素个数
int ListLength_L(LinkList L)
{
LinkList p;
int i;
if(L)
{
i = 0;
p = L->next;
while(p)
{
i++;
p = p->next;
}
}
return i;
}
//(06)算法2.8:用e接收单链表L中第i个元素
Status GetElem_L(LinkList L, int i, LElemType_L *e)
{
int j;
LinkList p = L->next;
j = 1;
p = L->next;
while(p && j<i) //p不为空且还未到达i处
{
j++;
p = p->next;
}
if(!p || j>i) //第i个元素不存在
return ERROR;
*e = p->data;
return OK;
}
//(07)返回单链表L中第一个与e满足Compare关系的元素位序
int LocateElem_L(LinkList L, LElemType_L e, Status(Compare)(LElemType_L, LElemType_L))
{
int i;
LinkList p;
i = -1; //L不存在时返回-1
if(L)
{
i = 0;
p = L->next;
while(p)
{
i++;
if(!Compare(e, p->data))
{
p = p->next;
if(p==NULL) //失配时已经是最后一个结点
i++;
}
else
break;
}
}
return i;
}
/* 银行排队算法中,此处两个函数不能直接使用,原因是结构不能直接比较 */
#ifndef BANKQUEUING_C
//(08)用pre_e接收cur_e的前驱
Status PriorElem_L(LinkList L, LElemType_L cur_e, LElemType_L *pre_e)
{
LinkList p, suc;
if(L)
{
p = L->next;
if(p->data!=cur_e) //第一个结点无前驱
{
while(p->next) //若p结点有后继
{
suc = p->next; //suc指向p的后继
if(suc->data==cur_e)
{
*pre_e = p->data;
return OK;
}
p = suc;
}
}
}
return ERROR;
}
//(09)用next_e接收cur_e的后继
Status NextElem_L(LinkList L, LElemType_L cur_e, LElemType_L *next_e)
{
LinkList p, suc;
if(L)
{
p = L->next;
while(p && p->next)
{
suc = p->next;
if(suc && p->data==cur_e)
{
*next_e = suc->data;
return OK;
}
if(suc)
p = suc;
else
break;
}
}
return ERROR;
}
#endif
//(10)算法2.9:在单链表L第i个位置之前插入e
Status ListInsert_L(LinkList L, int i, LElemType_L e)
{
LinkList p, s;
int j;
p = L;
j = 0;
while(p && j<i-1) //寻找第i-1个结点
{
p = p->next;
++j;
}
if(!p || j>i-1)
return ERROR;
s = (LinkList)malloc(sizeof(LNode));
if(!s)
exit(OVERFLOW);
s->data = e;
s->next = p->next;
p->next = s;
return OK;
}
//(11)算法2.10:删除单链表L第i个位置的值,并用e接收
Status ListDelete_L(LinkList L, int i, LElemType_L *e)
{
LinkList pre, p;
int j;
pre = L;
j = 1;
while(pre->next && j<i) //寻找第i个结点,并令pre指向其前驱
{
pre = pre->next;
++j;
}
if(!pre->next || j>i) //删除位置不合理
return ERROR;
p = pre->next;
pre->next = p->next;
*e = p->data;
free(p);
return OK;
}
//(12)用Visit函数访问单链表L
Status ListTraverse_L(LinkList L, void(Visit)(LElemType_L))
{
LinkList p;
if(!L)
return ERROR;
else
p = L->next;
while(p)
{
Visit(p->data);
p = p->next;
}
return OK;
}
//(13)算法2.11:头插法建立单链表L(逆序输入)
Status CreateList_HL(FILE *fp, LinkList *L, int n)
{
int i;
LinkList p;
LElemType_L tmp;
*L = (LinkList)malloc(sizeof(LNode));
if(!(*L))
exit(OVERFLOW);
(*L)->next = NULL; //建立头结点
for(i=1; i<=n; ++i)
{
if(Scanf(fp, "%d", &tmp)==1)
{
p = (LinkList)malloc(sizeof(LNode));
if(!p)
exit(OVERFLOW);
p->data = tmp; //录入数据
p->next = (*L)->next;
(*L)->next = p;
}
else
return ERROR;
}
return OK;
}
//(14)尾插法建立单链表L(顺序输入)
Status CreateList_TL(FILE *fp, LinkList *L, int n)
{
int i;
LinkList p, q;
LElemType_L tmp;
*L = (LinkList)malloc(sizeof(LNode));
if(!(*L))
exit(OVERFLOW);
(*L)->next = NULL;
for(i=1,q=*L; i<=n; ++i)
{
if(Scanf(fp, "%d", &tmp)==1)
{
p = (LinkList)malloc(sizeof(LNode));
if(!p)
exit(OVERFLOW);
p->data = tmp; //录入数据
q->next = p;
q = q->next;
}
else
return ERROR;
}
q->next = NULL;
return OK;
}
#endif
/*******************************************
* 文件夹: ▲02 线性表\04 SinglyLinkedList *
* 内 容: 单链表相关函数测试 *
*******************************************/
#include <stdio.h>
#include "SinglyLinkedList.c" //**▲02 线性表**//
/* 函数原型 */
Status CmpGreater(LElemType_L e, LElemType_L data); //判断data是否大于e //若data大于e,返回TRUE
void PrintElem(LElemType_L e); //测试函数,打印整型
int main(int argc, char **argv)
{
LinkList L;
int i;
LElemType_L e;
printf("▼1\n▲函数 InitList_L 测试...\n"); //1.函数InitList_L测试
{
printf("初始化单链表 L ...\n");
InitList_L(&L);
printf("\n");
}
PressEnter;
printf("▼4\n▲函数 ListEmpty_L 测试...\n"); //4.函数ListEmpty_L测试
{
ListEmpty_L(L) ? printf(" L 为空!!\n") : printf(" L 不为空!\n");
printf("\n");
}
PressEnter;
printf("▼10\n▲函数 ListInsert_L 测试...\n"); //10.函数ListInsert_L测试
{
for(i=1; i<=6; i++)
{
printf("在 L 第 %d 个位置插入 \"%d\" ...\n", i, 2*i);
ListInsert_L(L, i, 2*i);
}
printf("\n");
}
PressEnter;
printf("▼12\n▲函数 ListTraverse_L 测试...\n"); //12.函数ListTraverse_L测试
{
printf(" L 中的元素为:L = ");
ListTraverse_L(L, PrintElem);
printf("\n\n");
}
PressEnter;
printf("▼5\n▲函数 ListLength_L 测试...\n"); //5.函数ListLength_L测试
{
printf(" L 的长度为 %d \n", ListLength_L(L));
printf("\n");
}
PressEnter;
printf("▼11\n▲函数 ListDelete_L 测试...\n"); //11.函数ListDelete_L测试
{
ListDelete_L(L, 6, &e);
printf("删除 L 中第 6 个元素 \"%d\" ...\n", e);
printf(" L 中的元素为:L = ");
ListTraverse_L(L, PrintElem);
printf("\n\n");
}
PressEnter;
printf("▼6\n▲函数 GetElem_L 测试...\n"); //6.函数GetElem_L测试
{
GetElem_L(L, 4, &e);
printf(" L 中第 4 个位置的元素为 \"%d\" \n", e);
printf("\n");
}
PressEnter;
printf("▼7\n▲函数 LocateElem_L 测试...\n"); //7.函数LocateElem_L测试
{
i = LocateElem_L(L, 13, CmpGreater);
printf(" L 中第一个元素值大于 \"7\" 的元素的位置为 %d \n", i);
printf("\n");
}
PressEnter;
printf("▼8\n▲函数 PriorElem_L 测试...\n"); //8.函数PriorElem_L测试
{
PriorElem_L(L, 6, &e);
printf("元素 \"6\" 的前驱为 \"%d\" \n", e);
printf("\n");
}
PressEnter;
printf("▼9\n▲函数 NextElem_L 测试...\n"); //9.函数NextElem_L测试
{
NextElem_L(L, 6, &e);
printf("元素 \"6\" 的后继为 \"%d\" \n", e);
printf("\n");
}
PressEnter;
printf("▼2\n▲函数 ClearList_L 测试...\n"); //2.函数ClearList_L测试
{
printf("清空 L 前:");
ListEmpty_L(L) ? printf(" L 为空!!\n") : printf(" L 不为空!\n");
ClearList_L(L);
printf("清空 L 后:");
ListEmpty_L(L) ? printf(" L 为空!!\n") : printf(" L 不为空!\n");
printf("\n");
}
PressEnter;
printf("▼3\n▲函数 DestroyList_L 测试...\n"); //3.函数DestroyList_L测试
{
printf("销毁 L 前:");
L ? printf(" L 存在!\n") : printf(" L 不存在!!\n");
DestroyList_L(&L);
pri
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 详解linux dma驱动编写
- CentOS6.5环境安装nginx服务器及负载均衡配置操作详解
- 详解linux 驱动编写(sd卡驱动)
- Centos 6.9环境下创建用户及删除用户的方法
- 详解linux驱动编写(入门)
- Ubuntu使用国内源出现Hash Sum mismatch错误的解决
- CentOS基于nginx反向代理实现负载均衡的方法
- CentOS7服务器环境下vsftpd安装及配置方法
- Linux date 时间设置同步命令分享
- Gerrit设置开机启动方法
- Ubuntu服务器下搭建php运行环境的方法
- 详解ubuntu14.04搭建(迁移)hustoj记录
- linux 触摸屏驱动编写
- centos yum更新及删除多余启动项
- React进阶(1)-理解Redux