一.简述

  ...由于链表在空间的合理利用上和插入、删除时不需要移动等的优点,因此在很多场合下,它是线性表的首选存储结构。然而,它也存在着实现某些基本操作,如求线性表的长度时不如顺序存储结构的缺点;另一方面,由于在链表中,结点之间的关系用指针来表示,则数据元素在线性表中的“位序”的概念已经淡化,而被数据元素在线性链表中的“位置”所代替。为此,从实际应用的角度重新定义线性链表及其基本操作。....(Page37) 

  此外,书上一些地方我认为存在错误,所以写代码时做了修改和注释。并且,由于一些基本操作书中没有具体使用的实例,所以我只实现了算法2.20和算法2.21中出现的基本操作,其他操作会在需要的时候 再做实现。

  二.头文件

 //LinkList.h
/**
《数据结构(C语言版)》 Page 37
....为此,从实际应用角度出发重新定义线性链表及其基本操作....
*/
/**
author:zhaoyu
email:zhaoyu1995.com@gmail.com
date:2016-6-4
note:realize my textbook <<数据结构(C语言版)>>
*/
#ifndef _LINKLIST_H_
#define _LINKLIST_H_
#include "head.h"
#include <cstdlib>
#define ElemType int
typedef struct LNode{
ElemType data;
struct LNode *next;
}*Link, *Position;
typedef struct{//链表类型
Link head, tail;//分别指向线性链表中的头结点和最后一个结点
int len;//指示线性链表中数据元素的个数
}LinkList;
Status MakeNode(Link &p, ElemType e)
{
//分配由 p 指向的值为 e 的结点,并返回 OK;若分配失败,则返回 ERROR
p = (Link)malloc(sizeof(struct LNode));
if (!p)
{
return ERROR;
}
p->data = e;
p->next = NULL;
return OK;
}
Status FreeNode(Link &p)
{
//释放 p 所指节点
p = NULL;//便于回收???释放后再次使用
free(p);
}
Status InitList(LinkList &L)
{
//构造一个空的线性表L
L.head = (Link)malloc(sizeof(struct LNode));
L.head->data = ;
L.head->next = NULL;
L.tail = L.head->next;
L.len = ;
}
Status ClearList(LinkList &L)
{
//将线性链表置为空表并释放原链表的结点空间
}
Status InsFirst(LinkList &L, Link &h, Link &s)
{
//已知 h 指向线性链表的头结点,将 s 所指节点插入在第一个结点之前
//note:这里的参数与书上有些不一样,LinkList &L是我添加的
//因为插入新的元素之后,链表长度应该同步变化
//链表的插入是基于地址的,所以我全部加了引用
//这一个函数与书上参数完全不同
//更新 2016-5-5 16:46
//通过分析算法2.20发现 h 不是绝对的头结点,而是接受一个 h
//就以它为头结点作参考操作其它元素
//这个函数花了不少时间,值得反复思考
if (NULL == h)
{
return ERROR;
}
else
{
s->next = h->next;
h->next = s;
}
L.len++;
return OK;
}
Status DelFirst(Link &h, Link &q)
{
//已知 h 指向线性链表的头结点,删除链表中的第一个节点并以 q 返回
if (h == NULL)
{
return ERROR;
}
q = h->next;
h->next = q->next;
q->next = NULL;
return OK;
}
Status Append(LinkList &L, Link &s)
{
//将指针 s 所指(彼此以指针相链)的一串结点
//链接在线性链表 L 最后一个结点
Link q = L.head;
while (q->next != NULL)
{
q = q->next;
}
q->next = s;
int cnt = ;
Link temp = s;
while (temp != NULL)
{
cnt++;
if (NULL == temp->next)
{
L.tail = temp;//注意更新尾指针
}
temp = temp->next;
} L.len += cnt;
//注意要根据这一串结点长度增加链表长度
return OK;
}
Status Remove(LinkList &L, Link &q)
{
//删除线性链表 L 中的尾结点并以 q 返回,改变链表的尾指针指向新的尾结点
}
Status InsBefore(LinkList &L, Link &p, Link s)
{
//已知 p 指向线性链表 L 中的一个结点,将 s 所指结点插入 p 所指节点之前
//并修改指针 p 指向新插入的节点
}
Status InsAfter(LinkList &L, Link &p, Link s)
{
//已知 p 指向线性链表 L 中的一个结点,将 s 所指结点插入 p 所指节点之后
//并修改指针 p 指向新插入的节点
}
Status SetCurElem(Link &p, ElemType e)
{
//已知 p 指向线性链表中的一个结点,用 e 更新 p 所指结点中数据元素的值
}
ElemType GetCurElem(Link p)
{
//已知 p 指向线性链表中的一个节点,返回 p 所指结点中数据元素的值
if (p != NULL)
{
return p->data;
}
else
{
exit(ERROR);
}
}
Status ListEmpty(LinkList L)
{
//若线性链表 L 为空,则返回 TRUE,否则返回 FALSE
}
int ListLength(LinkList L)
{
//返回线性链表 L 中元素的个数 }
Position GetHead(LinkList L)
{
//返回线性链表 L 中头结点的位置
return L.head;
}
Position GetLast(LinkList L)
{
//返回线性链表 L 中最后一个结点的位置
}
Position PriorPos(LinkList L, Link p)
{
//已知 p 指向线性链表 L 中的一个结点,返回 p 所指结点直接前驱的位置
//若无前驱,则返回NULL
}
Position NextPos(LinkList L, Link p)
{
//已知 p 指向线性链表 L 中的一个节点,返回 p 所指结点
//的直接后继的位置,若无后继,返回 NULL
Link q = L.head;
while (q != NULL)
{
if(q == p)
{
return p->next;
}
q = q->next;
}
return NULL;
}
Status LocatePos(LinkList L, int i, Link &p)
{
//返回 p 指示线性链表 L 中第 i 个结点的位置并返回 OK
//i 值不合法时返回ERROR
int cnt = ;
p = L.head;
if (i > L.len || i < )
{
return ERROR;
}
while (cnt <= i)
{
p = p->next;
cnt++;
}
return OK; }
Position LocateElem(LinkList L, ElemType e, Status (* compare)(ElemType, ElemType))
{
//返回线性链表中第一个与 e 满足函数compare() 判定关系的元素的位置
//若不存在这样的元素,返回 NULL
}
Status ListTraverse(LinkList L, Status (* visit)())
{
//依次对 L 中每个元素调用函数 visit(),一旦visit() 失败,则操作失败。
}
/**
My Code
*/
void PrintList(LinkList L)
{
Link p = L.head->next;
int cnt = ;
while (p != NULL && cnt <= L.len)
{
printf("%d\t", p->data);
p = p->next;
cnt++;
}
printf("\n");
}
int compare(ElemType a, ElemType b)
{
if (a < b)
{
return -;
}
else if (a == b)
{
return ;
}
else
{
return ;
}
}
#endif

  三.CPP文件

 //LinkList.h
/**
《数据结构(C语言版)》 Page 37
....为此,从实际应用角度出发重新定义线性链表及其基本操作....
*/
/**
author:zhaoyu
email:zhaoyu1995.com@gmail.com
date:2016-6-4
note:realize my textbook <<数据结构(C语言版)>>
*/
#ifndef _LINKLIST_H_
#define _LINKLIST_H_
#include "head.h"
#include <cstdlib>
#define ElemType int
typedef struct LNode{
ElemType data;
struct LNode *next;
}*Link, *Position;
typedef struct{//链表类型
Link head, tail;//分别指向线性链表中的头结点和最后一个结点
int len;//指示线性链表中数据元素的个数
}LinkList;
Status MakeNode(Link &p, ElemType e)
{
//分配由 p 指向的值为 e 的结点,并返回 OK;若分配失败,则返回 ERROR
p = (Link)malloc(sizeof(struct LNode));
if (!p)
{
return ERROR;
}
p->data = e;
p->next = NULL;
return OK;
}
Status FreeNode(Link &p)
{
//释放 p 所指节点
p = NULL;//便于回收???释放后再次使用
free(p);
}
Status InitList(LinkList &L)
{
//构造一个空的线性表L
L.head = (Link)malloc(sizeof(struct LNode));
L.head->data = ;
L.head->next = NULL;
L.tail = L.head->next;
L.len = ;
}
Status ClearList(LinkList &L)
{
//将线性链表置为空表并释放原链表的结点空间
}
Status InsFirst(LinkList &L, Link &h, Link &s)
{
//已知 h 指向线性链表的头结点,将 s 所指节点插入在第一个结点之前
//note:这里的参数与书上有些不一样,LinkList &L是我添加的
//因为插入新的元素之后,链表长度应该同步变化
//链表的插入是基于地址的,所以我全部加了引用
//这一个函数与书上参数完全不同
//更新 2016-5-5 16:46
//通过分析算法2.20发现 h 不是绝对的头结点,而是接受一个 h
//就以它为头结点作参考操作其它元素
//这个函数花了不少时间,值得反复思考
if (NULL == h)
{
return ERROR;
}
else
{
s->next = h->next;
h->next = s;
}
L.len++;
return OK;
}
Status DelFirst(Link &h, Link &q)
{
//已知 h 指向线性链表的头结点,删除链表中的第一个节点并以 q 返回
if (h == NULL)
{
return ERROR;
}
q = h->next;
h->next = q->next;
q->next = NULL;
return OK;
}
Status Append(LinkList &L, Link &s)
{
//将指针 s 所指(彼此以指针相链)的一串结点
//链接在线性链表 L 最后一个结点
Link q = L.head;
while (q->next != NULL)
{
q = q->next;
}
q->next = s;
int cnt = ;
Link temp = s;
while (temp != NULL)
{
cnt++;
temp = temp->next;
if (NULL == temp->next)
{
L.tail = temp;//注意更新尾指针
}
} L.len += cnt;
//注意要根据这一串结点长度增加链表长度
return OK;
}
Status Remove(LinkList &L, Link &q)
{
//删除线性链表 L 中的尾结点并以 q 返回,改变链表的尾指针指向新的尾结点
}
Status InsBefore(LinkList &L, Link &p, Link s)
{
//已知 p 指向线性链表 L 中的一个结点,将 s 所指结点插入 p 所指节点之前
//并修改指针 p 指向新插入的节点
}
Status InsAfter(LinkList &L, Link &p, Link s)
{
//已知 p 指向线性链表 L 中的一个结点,将 s 所指结点插入 p 所指节点之后
//并修改指针 p 指向新插入的节点
}
Status SetCurElem(Link &p, ElemType e)
{
//已知 p 指向线性链表中的一个结点,用 e 更新 p 所指结点中数据元素的值
}
ElemType GetCurElem(Link p)
{
//已知 p 指向线性链表中的一个节点,返回 p 所指结点中数据元素的值
if (p != NULL)
{
return p->data;
}
else
{
exit(ERROR);
}
}
Status ListEmpty(LinkList L)
{
//若线性链表 L 为空,则返回 TRUE,否则返回 FALSE
}
int ListLength(LinkList L)
{
//返回线性链表 L 中元素的个数 }
Position GetHead(LinkList L)
{
//返回线性链表 L 中头结点的位置
return L.head;
}
Position GetLast(LinkList L)
{
//返回线性链表 L 中最后一个结点的位置
}
Position PriorPos(LinkList L, Link p)
{
//已知 p 指向线性链表 L 中的一个结点,返回 p 所指结点直接前驱的位置
//若无前驱,则返回NULL
}
Position NextPos(LinkList L, Link p)
{
//已知 p 指向线性链表 L 中的一个节点,返回 p 所指结点
//的直接后继的位置,若无后继,返回 NULL
Link q = L.head;
while (q != NULL)
{
if(q == p)
{
return p->next;
}
q = q->next;
}
return NULL;
}
Status LocatePos(LinkList L, int i, Link &p)
{
//返回 p 指示线性链表 L 中第 i 个结点的位置并返回 OK
//i 值不合法时返回ERROR
int cnt = ;
p = L.head;
if (i > L.len || i < )
{
return ERROR;
}
while (cnt <= i)
{
p = p->next;
cnt++;
}
return OK; }
Position LocateElem(LinkList L, ElemType e, Status (* compare)(ElemType, ElemType))
{
//返回线性链表中第一个与 e 满足函数compare() 判定关系的元素的位置
//若不存在这样的元素,返回 NULL
}
Status ListTraverse(LinkList L, Status (* visit)())
{
//依次对 L 中每个元素调用函数 visit(),一旦visit() 失败,则操作失败。
}
/**
My Code
*/
void PrintList(LinkList L)
{
Link p = L.head->next;
int cnt = ;
while (p != NULL && cnt <= L.len)
{
printf("%d\t", p->data);
p = p->next;
cnt++;
}
printf("\n");
}
int compare(ElemType a, ElemType b)
{
if (a < b)
{
return -;
}
else if (a == b)
{
return ;
}
else
{
return ;
}
}
#endif

  四.测试

数据结构算法C语言实现(五)---2.3重新定义线性链表及其基本操作的更多相关文章

  1. 数据结构算法C语言实现(六)---2.4一元多项式的表示及相加

    一.简述 利用链表表示稀疏多项式,并基于之前的一些操作(编程实现上还是有所不同的)组合新的操作实现一元多项式的表示及相加. 二.ADT 抽象数据类型一元多项式的定义 ADT Polyomail{ 数据 ...

  2. 数据结构算法C语言实现(一)---2.2线性表的顺序表示和实现

    注意: 虽然是用C语言实现,但是考虑到使用了一个C++的特性----引用以简化代码,所以所有的代码均以cpp作为后缀,用g++编译(以后不做说明). g++版本: 一.简述 本节主要讲述线性表的顺序实 ...

  3. 数据结构算法C语言实现(八)--- 3.2栈的应用举例:迷宫求解与表达式求值

    一.简介 迷宫求解:类似图的DFS.具体的算法思路可以参考书上的50.51页,不过书上只说了粗略的算法,实现起来还是有很多细节需要注意.大多数只是给了个抽象的名字,甚至参数类型,返回值也没说的很清楚, ...

  4. 数据结构算法C语言实现(十二)--- 3.4循环队列&队列的顺序表示和实现

    一.简述 空队列的处理方法:1.另设一个标志位以区别队列是空还是满:2.少用一个元素空间,约定以队列头指针在队尾指针下一位置上作为队列呈满的状态的标志. 二.头文件 //3_4_part1.h /** ...

  5. 数据结构算法C语言实现(十)--- 3.3栈与递归的实现

    一.简介 汉诺塔问题是递归的一个典型例子,而且书上的讲解很详细,对理解C语言函数及函数传参的工作机制很有帮助,值得一看.而且,递归在我看来和分治.DP.贪心等一样是十分优美的思想,值得学习!!! 二. ...

  6. 数据结构算法C语言实现(七)--- 3.1栈的线性实现及应用举例

    一.简述 栈,LIFO.是操作受限的线性表,和线性表一样有两种存储表示方法.下面以顺序存储为例,实现. 二.ADT 暂无. 三.头文件 //3_1.h /** author:zhaoyu email: ...

  7. 数据结构算法C语言实现(二)---2.3线性表的链式表示和实现之单链表

    一.简述 [暂无] 二.头文件 #ifndef _2_3_part1_H_ #define _2_3_part1_H_ //2_3_part1.h /** author:zhaoyu email:zh ...

  8. 数据结构算法C语言实现(二十七)--- 7.2图的遍历

    一.简述 栈与队列,DFS与BFS.仅以连接表为例实现. 二.头文件 BFS要用到的头文件 //3_4_part1.h /** author:zhaoyu email:zhaoyu1995.com@g ...

  9. 数据结构算法C语言实现(二十)--- 6.3.1遍历二叉树

    一.简述 二叉树的遍历主要是先序.中序.后序及对应的递归和非递归算法,共3x2=6种,其中后序非递归在实现上稍复杂一些.二叉树的遍历是理解和学习递归及体会栈的工作原理的绝佳工具! 此外,非递归所用的栈 ...

随机推荐

  1. Spring 4.0.2 学习笔记(1) - 最基本的注入

    1. 添加maven支持 <dependency> <groupId>org.springframework</groupId> <artifactId> ...

  2. 如何在 Apache 中为你的网站设置404页面

    一个好的网站,拥有一个好的 404页面 是标配. 为何要有 404页面?如何设置一个 404页面? why 404 pages? 在本地,比如我打开 localhost/fuck.htm(该文件不存在 ...

  3. 用H5+Boostrap做简单的音乐播放器

    前言:这个是综合一下我最近在学的东西做的小Demo,到实际使用还有距离,但是用来练手巩固知识点还是不错的,最近在二刷JS书和Boostrap.css的源码,做完这个Demo也算是暂告一段落,接下来是j ...

  4. 一步一步学习ABP项目系列文章目录

    1.概述 基于DDD的.NET开发框架 - ABP初探 基于DDD的.NET开发框架 - ABP分层设计 基于DDD的.NET开发框架 - ABP模块设计 基于DDD的.NET开发框架 - ABP启动 ...

  5. Centos|RHEL7以前解决网卡eth0相关问题

    网络-网络-有网才有络络,哈哈!学习在于不断记录,问题记录多了就成大牛了.当大牛达到一定层次,都会回馈社会.研发推出新的东东! CentOS找不到ifcfg-eth0解决方法 问题描述: ifconf ...

  6. TP学习笔记一(tp的目录结构 , tp的输出方式)

    一.ThinkPHP的介绍 //了解 MVC M - Model 模型 工作:负责数据的操作 V - View 视图(模板) 工作:负责前台页面显示 C - Controller 控制器(模块) 工作 ...

  7. 基于tomcat+spring+mysql搭建的个人博客

    基于tomcat和spring开发的个人博客, 服务器是基于tomcat, 用了spring框架, web.xml的配置简单明了,我们只要配置MYSQL和用户过滤器等, 服务器的jsp就是负责VIEW ...

  8. 100114C

    打表找规律 第25项开始循环 #include<iostream> #include<cstdio> #include<algorithm> using names ...

  9. Mysql-通过case..when实现oracle decode()函数进行多值多结果判断

    oracle的decode函数使用:http://www.cnblogs.com/hwaggLee/p/5335967.html case ..when 函数使用:http://www.cnblogs ...

  10. ps制作gif图片

    本文自学内容来自这里 PS版本是CS6: 制作效果 步骤 1.下载素材 2.打开ps,添加素材 文件->打开->选择所有需要的素材全部打开(如图,已将需要的3个素材全部打开) 3.将素材放 ...