《数据结构与算法分析——C语言描述》第三章 线性表基本概念学习总结和顺序表实现(C语言)

线性表的抽象数据类型描述:
类型名称:线性表
数据对象集:线性表是具有相同数据类型的n(n >= 0)个数据元素的有限序列。
操作集:(其中整数i表示位置,ElementType表示数据元素的类型,ptrl表示指向线性表的指针)

List Make_Empty( );                      //创建空表 
int find( ElementType x, List ptrl );    //查找元素,返回下标,若没找到返回-1
void insert( ElementType x, int i, List ptrl );  //插入函数,在第i个位置插入新元素 
void Delete( int i, List ptrl );                 //删除线性表中第i个元素 
int length ( List ptrl );                        //返回表长(即线性表中数据元素的个数)
ElementType find_k( int i, List ptrl );          //返回线性表中第i个元素
int Empty( List ptrl );                          //判断表空,如果表空,返回0;表不空,返回1 
void PrintList( List ptrl, int m, int n );       //打印从位置m到位置n的所有元素 
void DestoryList( ptrl );                        //销毁线性表并释放空间

线性表的逻辑特性:
线性表中数据元素的个数n称为表长,当n = 0时,称为空表,其中表的第一个数据元素称为表头元素,最后一个数据元素称为表尾元素,线性表中除了表头元素之外的每一个数据元素都有前驱元,除了表尾元素之外每一个数据元素都有后驱元。

线性表的特点:(王道总结)
(1)表中数据元素个数有限;
(2)表中元素在逻辑上有先后次序;
(3)表中元素都是数据元素,每个元素都是单个元素;
(4)表中元素的数据类型都相同,每个元素占用相同的内存空间;
(5)表中元素具有抽象性,仅讨论元素之中的逻辑关系,不考虑元素究竟表示什么内容。
(6)表中元素是一对一的相邻关系;

注意:顺序表和链表指的是线性表的存储结构,而线性表本身是逻辑结构。

线性表的顺序存储(C语言:数组):
线性表的顺序存储特点是表中数据元素的逻辑顺序和物理顺序相同。
顺序表的存储密度高,每个节点上只存储数据元素。

存储密度:在计算机中是指结点数据本身所占的存储量和整个结点结构所占的存储量之比,计算公式:存储密度 = (结点数据本身所占的存储量)/(结点结构所占的存储总量)。这里的结构一般指的是数据结构,主要通过计算机中数据的存储结构来影响存储密度。(来自百度百科)

具体实现如下(数组静态分配):

//线性表的数组实现
#include <stdio.h>
#include <stdlib.h>

#define ElementType int
#define Maxsize 10

typedef struct LNODE{
	ElementType data[ Maxsize ];
	int len; 
}node;

typedef node* List;

List Make_Empty( );                      //创建空表 
int find( ElementType x, List ptrl );    //查找元素,返回下标,若没找到返回-1
void insert( ElementType x, int i, List ptrl );  //插入函数,在第i个位置插入新元素 
void Delete( int i, List ptrl );                 //删除线性表中第i个元素 
int length ( List ptrl );                        //返回表长(即线性表中数据元素的个数)
ElementType find_k( int i, List ptrl );          //返回线性表中第i个元素
int Empty( List ptrl );                          //判断表空,如果表空,返回0;表不空,返回1 
void PrintList( List ptrl, int m, int n );       //打印从位置m到位置n的所有元素 

int main ( void )
{
	List ptrl;
	ptrl = Make_Empty( );
	int i;
	for( i = 1; i < Maxsize; i++ ){
		ptrl -> data[i - 1] = i;
		ptrl -> len++;
	}
	
	if( Empty( ptrl ) == 0 )
		printf( "表空\n" );
	else 
		printf( "表不空\n" );
		 
	int len = length( ptrl ); 
	printf( "表长len = %d\n", len );
	
	int index = find( 8, ptrl );
	printf( "8的下标index = %d\n", index );
	
	ElementType m = find_k( 5, ptrl );
	printf( "第5个位置上的元素m = %d\n", m );
	
	PrintList( ptrl, 1, len );
	insert( 88, 9, ptrl );
	PrintList( ptrl, 1, len + 1 );
	Delete( 6, ptrl );
	PrintList( ptrl, 1, len );
	
	return 0;
}

List Make_Empty( )
{
	List ptrl;
	ptrl = ( List )malloc( sizeof( node ) );
	if( ptrl == NULL )
		printf( "申请空间出错\n" );
	ptrl -> len = 0;
	return ptrl;
}

int find( ElementType x, List ptrl )
{
	int j = 0;
	while( j <= ptrl -> len - 1 && ptrl -> data[j] != x )
		j++;
	if( j > ptrl -> len - 1 )
		return -1;
	else
		return j + 1;
}

void insert( ElementType x, int i, List ptrl )
{
	if( ptrl -> len == Maxsize ){
		printf( "表满\n" );
		return ; 
	}
	if( i < 1 || i > ptrl -> len + 1 ){
		printf( "位置不合法\n" );
		return ;
	}
	int j;
	for( j = ptrl -> len - 1; j >= i - 1; j-- ){
		ptrl -> data[j + 1] = ptrl -> data[j];
	}
	ptrl -> data[i - 1] = x;
	ptrl -> len++;
	return ;
} 

void Delete( int i, List ptrl )
{
	int j;
	if( i < 1 || i > ptrl -> len ){
		printf( "位置不合法\n" );
		return; 
	}
	for( j = i ; j <= ptrl -> len - 1; j++ )
		ptrl -> data[j - 1] = ptrl -> data[j];
	ptrl -> len--;
	return ;
}

int length ( List ptrl )
{
	return ptrl -> len;
}

void PrintList( List ptrl, int m, int n )
{
	int i;
	for( i = m; i <= n; i++ )
		printf( "%d ", find_k( i, ptrl ) );
	printf( "\n" );
} 

ElementType find_k( int i, List ptrl )
{
	return ptrl -> data[i - 1];
}

int Empty( List ptrl )
{
	return !( ptrl -> len == 0 );
}

我在主函数中做了一些测试,用来检验函数的正确性,在整个代码中需要注意一个问题,就是在线性表中元素的序号使用的从1开始的自然序列,而在实现的过程中数组的下标是从0开始的。

从上面可以看出来,顺序表(数组实现)的方法在插入和删除操作上花费的时间代价是昂贵的,平均来看,这两种运算都需要移动表的一半的元素,因此需要线性时间(即O(n)),但顺序表在查找上比较方便,通过首地址和元素序号就可在O(1)的时间内找到指定的元素,只通过相继插入来建立一个表需要O(n^2)的时间。

顺序表(数组)的动态分配实现只需要把上面静态实现的相对应语句改成下面语句:

typedef struct LNODE{
	ElementType *data;
	int len; 
}node;
List Make_Empty( )
{
	List ptrl;
	ptrl = ( List )malloc( sizeof( node ) );
	if( ptrl == NULL )
		printf( "申请空间出错\n" );
	ptrl -> data = ( ElementType *)malloc( sizeof( ElementType ) * Maxsize ); 
	if( ptrl -> data == NULL )
			printf( "申请空间出错\n" );
	ptrl -> len = 0;
	return ptrl;
}

这样就可以实现数组分配的空间大小可以在运行时决定。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

房东的小黑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值