一个单链式实现的线性表 mList (GCC编译)。
/**
* @brief 线性表的链式实现 (单链表)
* @author wid
* @date 2013-10-21
*
* @note 若代码存在 bug 或程序缺陷, 请留言反馈, 谢谢!
*/
#include
#include
#define TRUE 1
#define FALSE 0
typedef struct
{
int x;
int y;
}Point2D; //Point2D 结构
typedef Point2D ElemType; //声明 Point2D 结构的别名 ElemType
typedef struct LNode
{
Point2D pt;
struct LNode *next;
}ListNode; //线性表数据项结构
typedef struct
{
ListNode *head; //数据项头节点
int length; //线性表长度
}mList; //线性表 mList 结构
//线性表方法声明
mList *CreateList(); ///创建一个空的线性表
void DestroyList( mList *pList ); ///销毁一条线性表
void ClearList( mList *pList ); ///置空一条线性表
int GetLength( mList *pList ); ///获取线性表当前长度
int IsEmpty( mList *pList ); ///检测线性表是否为空
int AppendElem( mList *pList, ElemType *pt ); ///向线性表末尾添加一个元素
int InsertElem( mList *pList, int nPos, ElemType *pt ); ///向线性表中插入一个元素
int DeleteElem( mList *pList, int nPos ); ///从线性表中删除一个元素
int GetElem( mList *pList, int nPos, ElemType *pt ); ///获取线性表中某位置上的元素
int FindElem( mList *pList, int nPos, ElemType *pt ); ///从某位置起查找某元素在线性表中第一次出现的位置
int GetPriorElem( mList *pList, ElemType *pt, ElemType *prior_pt ); ///从线性表中获取 pt 的前驱节点到 prior_pt
int GetNextElem( mList *pList, ElemType *pt, ElemType *next_pt ); ///从线性表中获取 pt 的后继节点到 next_pt
void ForEachList( mList *pList, void (*func)(ElemType *pt) ); ///对线性表中每个元素执行 func 函数
int ListCpy( mList *pDestList, mList *pSrcList ); ///将一线性表复制到另一线性表后
int ListCat( mList *pDestList, mList *pSrcList ); ///将一线性表连接到另一线性表后
//线性表方法实现
/**
* @brief 创建一个空的线性表
*
* @return 指向创建的线性表的指针
*/
mList *CreateList()
{
mList *pList = (mList *)malloc(sizeof(mList));
pList->head = (ListNode *)malloc(sizeof(ListNode));
pList->head->next = NULL;
pList->length = ;
return pList;
}
/**
* @brief 销毁一条线性表
*
* @param 指向待销毁的线性表的指针
*
* @return void
*/
void DestroyList( mList *pList )
{
ListNode *pm = pList->head, *pn = NULL;
while( pm != NULL )
{
pn = pm->next;
free(pm);
pm = pn;
}
free(pList);
pList = NULL;
}
/**
* @brief 置空一条线性表
*
* @param 指向待置空的线性表指针
*
* @return void
*/
void ClearList( mList *pList )
{
ListNode *pm = pList->head, *pn = NULL;
while( pm != NULL )
{
pn = pm->next;
free(pm);
pm = pn;
}
pList->head->next = NULL;
pList->length = ;
}
/**
* @brief 获取线性表当前长度
*
* @param 指针待获取长度的线性表的指针
*
* @return 返回获取到的线性表长度
*/
int GetLength( mList *pList )
{
return pList->length;
}
/**
* @brief 检测线性表是否为空
*
* @param pList 指向待检测的线性表的指针
*
* @return 若为空则返回 TRUE, 否则返回 FALSE
*/
int IsEmpty( mList *pList )
{
return pList->length == ? TRUE : FALSE;
}
/**
* @brief 向线性表末尾添加一个元素
*
* @param pList 目标线性表
* @param pe 指向待添加元素的指针
*
* @return 返回添加成功后当前线性表长度
*/
int AppendElem( mList *pList, ElemType *pt )
{
ListNode *pm = pList->head, *pn = NULL;
while( pm->next != NULL ) { pm = pm->next; };
pn = (ListNode *)malloc(sizeof(ListNode));
pn->pt.x = pt->x;
pn->pt.y = pt->y;
pn->next = NULL;
pm->next = pn;
return ++pList->length;
}
/**
* @brief 向线性表中插入一个元素
*
* @param pList 指向待插入元素的线性表
* @param nPos 插入的位置
* @param pt 指向待插入的元素的指针
*
* @return 若插入成功则返回插入后线性表当前长度, 否则返回 -1
*
* @note 插入位置 nPos 从 0 计起
*/
int InsertElem( mList *pList, int nPos, ElemType *pt )
{
ListNode *pm = pList->head, *pn = NULL;
if( nPos < || nPos > pList->length - ) ///插入位置是否在线性表内
return -;
int n = ;
for( n = ; n < nPos; ++n, (pm = pm->next) );
pn = (ListNode *)malloc(sizeof(ListNode));
pn->pt.x = pt->x;
pn->pt.y = pt->y;
pn->next = pm->next;
pm->next = pn;
return ++pList->length;
}
/**
* @brief 从线性表中删除一个元素
*
* @param pList 指向待删除元素的线性表指针
* @param nPos 待删除元素的位置
*
* @return 若删除成功则返回删除后线性表当前长度, 否则返回 -1
*
* @note 删除位置 nPos 从 0 计起
*/
int DeleteElem( mList *pList, int nPos )
{
ListNode *pm = pList->head, *pn = NULL;
if( nPos < || nPos > pList->length - ) ///删除位置是否在线性表内
return -;
int i = ;
for( i = ; i < nPos; ++i, (pm = pm->next) );
pn = pm->next;
pm->next = pn->next;
free(pn);
return --pList->length;
}
/**
* @brief 获取线性表中某位置上的元素
*
* @param pList 指向待获取元素的线性表指针
* @param nPos 元素在线性表中的位置
* @param pt 指向存放获取到的元素的指针
*
* @return 若获取成功, 返回 TRUE, 否则返回 FALSE
*
* @note 元素位置从 0 计起
*/
int GetElem( mList *pList, int nPos, ElemType *pt )
{
int n = nPos;
if( n < || n > pList->length - )
return FALSE;
ListNode *pm = pList->head;
for( n = ; n <= nPos; ++n, (pm = pm->next) );
pt->x = pm->pt.x;
pt->y = pm->pt.y;
return TRUE;
}
/**
* @brief 从某位置起查找某元素在线性表中第一次出现的位置
*
* @param pList 指向待查找元素的线性表的指针
* @param nPos 查找起始位置
* @param pt 指向待查找的元素的指针
*
* @return 若找到, 则返回元素所在的位置, 否则返回 -1
*
* @note 起始位置由 0 计起
*/
int FindElem( mList *pList, int nPos, ElemType *pt )
{
int n = nPos;
if( n < || n > pList->length - )
return -;
ListNode *pm = pList->head;
for( n = ; n <= nPos; ++n, (pm = pm->next) );
for( ; pm != NULL; ++n )
{
if( (pm->pt.x == pt->x) && (pm->pt.y == pt->y) )
return n-;
pm = pm->next;
}
return -;
}
/**
* @brief 获取某 pt 元素的前驱节点到 prior_pt
*
* @param 指向待获取前驱节点的线性表指针
* @param pt 指向目标节点的指针
* @param prior_pt 存放目标节点 pt 的前驱节点
*
* @return 若成功获取前驱节点, 返回该前驱节点在线性表中的位置, 否则返回 -1
*
* @note 元素位置从 0 计起
*/
int GetPriorElem( mList *pList, ElemType *pt, ElemType *prior_pt )
{
ListNode *pm = pList->head;
int ncnt = ;
while( pm->next != NULL )
{
if( pm->next->pt.x == pt->x && pm->next->pt.y == pt->y )
{
if( ncnt != ) ///不为首节点
{
prior_pt->x = pm->pt.x;
prior_pt->y = pm->pt.y;
return ncnt - ;
}
else return -; ///不存在前驱节点
}
pm = pm->next;
++ncnt;
}
return -;
}
/**
* @brief 获取某 pt 元素的后继节点到 next_pt
*
* @param 指向待获取前后继点的线性表指针
* @param pt 指向目标节点的指针
* @param prior_pt 存放目标节点 pt 的后继节点
*
* @return 若成功获取后继节点, 返回该后继节点在线性表中的位置, 否则返回 -1
*
* @note 元素位置从 0 计起
*/
int GetNextElem( mList *pList, ElemType *pt, ElemType *next_pt )
{
ListNode *pm = pList->head;
int ncnt = ;
while( (pm = pm->next) != NULL )
{
if( ncnt == pList->length ) //bug修复, 不存在后继节点
return -1;
if( pm->pt.x == pt->x && pm->pt.y == pt->y )
{
if( pm->next != NULL )
{
next_pt->x = pm->next->pt.x;
next_pt->y = pm->next->pt.y;
return ncnt + ;
}
}
++ncnt;
}
return -;
}
/**
* @brief 对线性表中每个元素执行 func 函数
*
* @param pList 指向待处理的线性表的指针
* @param func 传入的函数指针
*
* @return void
*/
void ForEachList( mList *pList, void (*func)(ElemType *pt) )
{
ListNode *pm = pList->head;
while( (pm = pm->next) != NULL )
func( &pm->pt );
}
/**
* @brief 将 pSrcList 性表复制到 pDestList 线性表后
*
* @param pDestList 指向目标线性表指针
* @param pSrcList 指向源线性表指针
*
* @return 返回复制后目标线性表长度
*/
int ListCpy( mList *pDestList, mList *pSrcList )
{
ListNode *pm = pDestList->head;
ListNode *pn = pSrcList->head;
ListNode *ptmp = NULL;
while( pm->next != NULL ) pm = pm->next;
while( (pn = pn->next) != NULL )
{
ptmp = (ListNode *)malloc(sizeof(ListNode));
ptmp->pt.x = pn->pt.x;
ptmp->pt.y = pn->pt.y;
pm->next = ptmp;
pm = pm->next;
}
pm->next = NULL;
pDestList->length += pSrcList->length;
return pDestList->length;
}
/**
* @brief 将 pSrcList 性表连接到 pDestList 线性表后
*
* @param pDestList 指向目标线性表指针
* @param pSrcList 指向源线性表指针
*
* @return 返回连接后目标线性表长度
*
* @note 连接后 pSrcList 线性表将被销毁
*/
int ListCat( mList *pDestList, mList *pSrcList )
{
ListNode *pm = pDestList->head;
while( pm->next != NULL ) pm = pm->next;
pm->next = pSrcList->head->next;
pDestList->length += pSrcList->length;
free( pSrcList );
return pDestList->length;
}
//测试 mList
void display( ElemType *pt )
{
printf("(%d,%d) ", pt->x, pt->y);
}
int main()
{
mList *plstA = CreateList(), *plstB = CreateList(); //创建 plst 与 plst2 两根空线性表
ElemType pt, pt2; //两个 ElemType 型元素
int i = ;
for( i = ; i < ; ++i )
{
pt.x = i;
pt.y = i;
AppendElem( plstA, &pt ); //向 plst 循环添加 (0,0) 至 (10,10)
}
for( i = ; i < ; ++i )
{
pt.x = i;
pt.y = i;
AppendElem( plstB, &pt ); //向 plst 循环添加 (55,55) 至 (60,60)
}
///测试 ForEachList
printf("plstA 初始数据: ");
ForEachList( plstA, display ); //对线性表中每个元素执行 display 函数
printf("\nplstB 初始数据: ");
ForEachList( plstB, display );
///测试 InsertElem
printf("\n\n向 plstA 位置3处插入元素(100,99)后:\n");
pt.x = ; pt.y = ;
InsertElem( plstA, , &pt ); //向 plstA 位置 3 处插入 pt
ForEachList( plstA, display );
///测试 DeleteElem
printf("\n\n删除 plstB 位置0处的元素后:\n");
DeleteElem( plstB, ); //删除 plstA 位置 0 处的元素
ForEachList( plstB, display );
///测试 IsEmpty、GetLength
printf("\n\n线性表 plstA 是否为空: %d\n", IsEmpty(plstA) );
printf("线性表 plstB 的长度: %d\n", GetLength(plstB) );
///测试 GetElem
GetElem( plstA, , &pt );
printf("获取 plstA 位置 5 的元素: (%d, %d)\n", pt.x, pt.y );
///测试 FindElem
pt.x = ; pt.y = ;
printf("获取元素(6,6)在线性表plstA中的位置: %d\n", FindElem(plstA, , &pt));
///测试 GetPriorElem
GetPriorElem( plstA, &pt, &pt2 );
printf("获取pt=(6,6)在plstA中的前驱节点: (%d,%d)\n", pt2.x, pt2.y);
///测试 GetNextElem
GetNextElem( plstA, &pt, &pt2 );
printf("获取pt=(6,6)在plstA中的后继节点: (%d,%d)\n", pt2.x, pt2.y);
///测试 ListCpy
printf("\n将 plstB 复制到 plstA 后:\n");
ListCpy( plstA, plstB );
ForEachList( plstA, display );
printf("\nplstA长度=%d\n", GetLength(plstA));
///测试 ListCat
printf("\n将 plstB 连接到 plstA 后:\n");
ListCat( plstA, plstB );
ForEachList( plstA, display );
printf("\nplstA长度=%d\n", GetLength(plstA));
///测试 ClearList
printf("\n置空 plstA 线性表:\n");
ClearList(plstA);
printf("plstA 长度=%d\n", GetLength(plstA));
///测试 DestroyList
printf("销毁 plstA..");
DestroyList(plstA);
return ;
}
若代码存在 bug 或程序缺陷, 请留言反馈, 谢谢。
javascript实现数据结构:线性表--线性链表(链式存储结构)
上一节中, 线性表的顺序存储结构的特点是逻辑关系上相邻的两个元素在物理位置上也相邻,因此可以随机存取表中任一元素,它的存储位置可用一个简单,直观的公式来表示.然后,另一方面来看,这个特点也造成这种存储 ...
C++编程练习(2)----“实现简单的线性表的链式存储结构“
单链表采用链式存储结构,用一组任意的存储单元存放线性表的元素. 对于查找操作,单链表的时间复杂度为O(n). 对于插入和删除操作,单链表在确定位置后,插入和删除时间仅为O(1). 单链表不需要分配存储 ...
c数据结构 -- 线性表之 复杂的链式存储结构
复杂的链式存储结构 循环链表 定义:是一种头尾相接的链表(即表中最后一个结点的指针域指向头结点,整个链表形成一个环) 优点:从表中任一节点出发均可找到表中其他结点 注意:涉及遍历操作时,终止条件是判断 ...
c数据结构 -- 线性表之 顺序存储结构 于 链式存储结构 (单链表)
线性表 定义:线性表是具有相同特性的数据元素的一个有限序列 类型: 1:顺序存储结构 定义:把逻辑上相邻的数据元素存储在物理上相邻的存储单元中的存储结构 算法: #include
C++线性表的链式存储结构
C++实现线性表的链式存储结构: 为了解决顺序存储不足:用线性表另外一种结构-链式存储.在顺序存储结构(数组描述)中,元素的地址是由数学公式决定的,而在链式储存结构中,元素的地址是随机分布的,每个元素 ...
线性表->;链式存储->;循环链表
文字描述 循环链表是另一种形式的链式存储结构.它的特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环.由此,从表中任一结点出发均可找到表中其他结点. 示意图 算法分析 插入.删除.查找等同单 ...
C语言实现链表(链式存储结构)
链表(链式存储结构)及创建 链表,别名链式存储结构或单链表,用于存储逻辑关系为 "一对一" 的数据.与顺序表不同,链表不限制数据的物理存储状态,换句话说,使用链表存储的数据元素,其 ...
PTA 带头结点的链式表操作集
6-2 带头结点的链式表操作集 (20 分) 本题要求实现带头结点的链式表操作集. 函数接口定义: List MakeEmpty(); Position Find( List L, Element ...
随机推荐
ITK 4.8.1 Qt 5.4 MinGW 4.9.1 Configuration 配置
Download ITK 4.8.1 Download Qt 5.4 with MinGW 4.9.1 Download CMake 3.2.0 I assume you've already ins ...
iOS一分钟学会环形进度条
有几篇博客写到了怎么实现环形进度条,大多是使用Core Graph来实现,实现比较麻烦且效率略低,只是一个小小的进度条而已,我们当然是用最简单而且效率高的方式来实现.先看一下这篇博客,博客地址:htt ...
FileWriter
package file; import java.io.File; import java.io.FileWriter; import java.io.IOException; public cla ...
Android -------- 从一个Fragment跳转到另一个Fragment
一.直接getActivity,使用activity的fragmenttransation的replace方法替换 private void changeToAnotherFragment(){ // ...
牵一发动全身【Nhibernate基本映射】
用牵一发动全身来形容Nhibernate的映射,一点都不夸张.小小的属性的修改,决定了整个Nhibernate的执行动态.以下让我们来详细了解一下,通过回想我们在上篇文章中用到的配置文件,做一个对xm ...
vim插件ctags的安装与使用
LINUX系统下看程序或者编程序时,看到一个函数经常需要知道该函数的定义,这时ctags就派上用场了,其安装和使用方法如下: 安装方法: sudo apt-get install ctags (ubu ...
MySQL 笔记(Mysql 8.0.16)
用户登陆 mysql -u user_name -p 修改密码 ALTER USER 'root'@'localhost' IDENTIFIED BY 'new_password'; 关闭服务 D:\ ...
python爬虫之git的安装
一.初始 1.发展历史 *最开始没有对代码的管理,导致很多东西混乱和丢失. *后来大家想了一个办法,用最简单最笨的方法,各种复制文件夹. *然后就出现了版本控制的工具. 1.单机版:RCS(198 ...
Methods to reduce the number of pipeline stages
Several techniques have been proposed to reduce the number of pipeline stages. We categorize them in ...