【数据结构】Liner-List 线性表(更新时间:2016-04-06)
趁着室友刚刚开始学习数据结构,赶紧配合着他的进度来写关于数据结构的相关内容
博文中的代码均使用C++语法,部分代码(主要是函数重载等)无法在C语言环境下编译
线性表 是最简单、最基本也是最常用的数据结构,它是以数组为基础定义的使得所需要的 元素 和 存储空间 一一对应的一种数据结构,即每一个存储元素都对应于一个特定的存储位置。
常见的线性表是用数组来存储,也就是我们常说的顺序存储:
struct ListNode; //定义线性表表头节点
typedef ListNode* PtrToNode; //定义线性表表头指针
typedef PtrToNode LinerList; //重定义表头指针
typedef int ElementType; //重定义数据类型
struct ListNode //数据结构描述
{
int capacity; //表的容量
int tail; //指向当前表的尾部
ElementType* Element; //数据域
};
const int MAX_CAP = 100; //初始容量
示意图:
基础操作
初始化
将线性表初始化,通过指针操作,将表头地址传入初始化函数,并以指针的形式返回表头。初始化表的容量以及表的尾指针。
LinerList Initial( void ) //表的初始化
{
LinerList L = NULL;
L = ( LinerList ) malloc ( sizeof(ListNode) ); //分配表头地址
L->capacity = MAX_CAP; //初始化数值域空间
L->tail = 0; //表尾部指针指向表头
L->Element = ( ElementType* ) malloc( L->capacity * sizeof( ElementType ) ); //分配数值域地址
return L; //返回表头
}
删除表
将整个线性表删除,表头置为空指针
void Delete( LinerList L ) //表的删除
{
if( L != NULL )
{
free( L->Element ); //释放数值域空间
free( L ); //释放表头
L = NULL; //表头置空
}
}
扩充表
在我们向线性表中插入数据的时候,由于线性表的有限性,会出现线性表容量溢出的情况,在这种情况下,我们可以使用realloc
函数来达到重新分配数值空间的目的。
LinerList Expansion( LinerList L ) //表的扩容
{
L->capacity++; //容量扩充
L->Element = ( ElementType* ) realloc ( L->Element, L->capacity * sizeof( ElementType ) ); //重分配数据空间
}
查找
对于线性表,我们经常需要查询其中是否存在某特定的元素。
int Find( const LinerList L, const ElementType X ) //查找元素
{
int pos = 0; //游标初始化
while( L->Element[pos] != X && pos < L->tail ) //游标遍历搜索
pos++;
if( pos != L->tail ) //如果找到返回pos
return pos;
else
return 0;
}
插入元素
对于线性表的插入主要分为简单插入和定点插入两种(使用函数重载来进行插入类别的判断):
简单插入 是指直接在表的尾部插入元素,如果表已满,则对表进行扩容。
LinerList Insert( LinerList L, const ElementType X ) //简单插入
{
if( L->tail == L->capacity ) //判断是否过载
Expansion( L ); //扩容
L->Element[ L->tail++ ] = X; //插入
return L; //返回表头
}
定点插入 是指插入位置与表的容量和表尾的相对状况进行插入,当插入位置在表尾内,则插入元素,如果插入位置非法,则返回原表。
LinerList Insert( LinerList L, const ElementType X, const int Pos ) //定点插入
{
int p = L->tail; //游标指向表尾
if( Pos > L->tail ) //判断插入位置合法性
{
cout << "Wrong insert position!\n";
return L;
}
if( L->tail == L->capacity ) //判断是否过载
{
Expansion( L );
L->tail++;
}
for( ; p > Pos; p-- ) //将数值逐个后移
L->Element[p+1] = L->Element[p];
L->Element[p] = X; //插入
}
删除元素
在线性表的使用过程中,除了插入一些元素之外,我们还需要删除一些元素。删除顺序线性表的方法是使用后面的元素填充到前面的元素之中。插入也分为简单删除和定点删除。由于代码中的Element类型为int,故暂时无法使用函数重载来在同一个代码区实现。
简单删除 调用代码中的Find
函数来查找所要删除的元素是否出现在表中,如果出现则删除。
LinerList Delete( LinerList L, const ElementType X ) //简单删除
{
int pos = Find( L, X ); //游标初始化
if( !pos ) //未找到指定元素
{
cout << X << " is not found in the LinerList!\n";
return L;
}
else
{
L->tail--; //尾表前移
while( pos < L->tail ) //元素逐个前移
L->Element[pos] = L->Element[pos+1];
return L;
}
}
定点删除 同定点插入。
LinerList Delete( LinerList L, const int Pos ) //定点删除
{
int p = Pos;
if( Pos > L->tail || Pos < 0 ) //判断是否越界
{
cout << "Wrong deletion postion!\n";
return L;
}
L->tail--; //尾标前移
while( p < L->tail ) //元素逐个前移
L->Element[p] = L->Element[p+1];
return L;
}
打印表
在使用线性表的时候我们会需要将表格打印出来,在这里简单示例用空格隔开每个元素。
void Print( const LinerList L ) //打印表
{
int pos = 0; //游标初始化
if( L == NULL )
{
cout << "Empty List!\n";
return;
}
while( pos < L->tail )
{
cout << L->Element[pos] << ' '; //打印元素并添加空格
pos++;
}
cout << endl; //输出换行
}
代码示例
注:其中的一个删除元素的函数被注释掉了,不体现实际功能
#include <cstdio>
#include <cstdlib>
#include <iostream>
using namespace std;
/*********************************************************/
struct ListNode; //定义线性表表头节点
typedef ListNode* PtrToNode; //定义线性表表头指针
typedef PtrToNode LinerList; //重定义表头指针
typedef int ElementType; //重定义数据类型
struct ListNode //数据结构描述
{
int capacity; //表的容量
int tail; //指向当前表的尾部
ElementType* Element; //数据域
};
const int MAX_CAP = 100; //初始容量
/*********************************************************/
void Delete( LinerList L ); //表的删除
LinerList Initial( void ); //表的初始化
LinerList Expansion( LinerList L ); //表的扩充
int Find( const LinerList L, const ElementType X ); //查找元素
LinerList Insert( LinerList L, const ElementType X ); //简单插入
LinerList Insert( LinerList L, const ElementType X, const int Pos ); //定点插入
LinerList Delete( LinerList L, const ElementType X ); //简单删除
LinerList Delete( LinerList L, const int Pos ); //定点删除
void Print( const LinerList L ); //打印表
/*********************************************************/
int main()
{
LinerList L;
ElementType X;
int i;
L = Initial();
for( i = 0; i < MAX_CAP-1; i++ )
Insert( L, i );
Insert( L, 99 );
Insert( L, 100, 100 );
Print( L );
Insert( L, 101, 102 );
Delete( L, 103 );
Delete( L );
}
/*********************************************************/
void Delete( LinerList L ) //表的删除
{
free( L->Element ); //释放表的数值域空间
free( L ); //释放表头
L = NULL; //表头置空
}
LinerList Initial( void ) //表的初始化
{
LinerList L = NULL;
L = ( LinerList ) malloc ( sizeof(ListNode) ); //分配表头地址
L->capacity = MAX_CAP; //初始化数值域空间
L->tail = 0; //表尾部指针指向表头
L->Element = ( ElementType* ) malloc( L->capacity * sizeof( ElementType ) ); //分配数值域地址
return L; //返回表头
}
LinerList Expansion( LinerList L ) //表的扩容
{
L->capacity++; //容量扩充
L->Element = ( ElementType* ) realloc ( L->Element, L->capacity * sizeof( ElementType ) ); //重分配数据空间
}
int Find( const LinerList L, const ElementType X ) //查找元素
{
int pos = 0; //游标初始化
while( L->Element[pos] != X && pos < L->tail ) //游标遍历搜索
pos++;
if( pos != L->tail ) //如果找到则返回pos
return pos;
else
return 0;
}
LinerList Insert( LinerList L, const ElementType X ) //简单插入
{
if( L->tail == L->capacity ) //判断是否过载
Expansion( L ); //扩容
L->Element[ L->tail++ ] = X; //插入
return L; //返回表头
}
LinerList Insert( LinerList L, const ElementType X, const int Pos ) //定点插入
{
int p = L->tail; //游标指向表尾
if( Pos > L->tail ) //判断插入位置合法性
{
cout << "Wrong insert position!\n";
return L;
}
if( L->tail == L->capacity ) //判断是否过载
{
Expansion( L );
L->tail++;
}
for( ; p > Pos; p-- ) //将数值逐个后移
L->Element[p+1] = L->Element[p];
L->Element[p] = X; //插入
}
LinerList Delete( LinerList L, const ElementType X ) //简单删除
{
int pos = Find( L, X ); //游标初始化
if( !pos ) //未找到指定元素
{
cout << X << " is not found in the LinerList!\n";
return L;
}
else
{
L->tail--; //尾表前移
while( pos < L->tail ) //元素逐个前移
L->Element[pos] = L->Element[pos+1];
return L;
}
}
/*
LinerList Delete( LinerList L, const int Pos ) //定点删除
{
int p = Pos;
if( Pos > L->tail || Pos < 0 ) //判断是否越界
{
cout << "Wrong deletion postion!\n";
return L;
}
L->tail--; //尾标前移
while( p < L->tail ) //元素逐个前移
L->Element[p] = L->Element[p+1];
return L;
}
*/
void Print( const LinerList L ) //打印表
{
int pos = 0; //游标初始化
if( L == NULL )
{
cout << "Empty List!\n";
return;
}
while( pos < L->tail )
{
cout << L->Element[pos] << ' '; //打印元素并添加空格
pos++;
}
cout << endl; //输出换行
}