《数据结构与算法分析——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)表中元素具有抽象性,仅讨论元素之中的逻辑关系,不考虑元素究竟表示什么内容。
(5)表中元素是一对一的相邻关系。

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

线性表的顺序存储(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;
}

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

猜你喜欢

转载自blog.csdn.net/qq_40344308/article/details/88528671