数据结构:线性表顺序存储结构 C语言版

线性表的定义:

线性表(List): 零个或多个数据元素的有序序列。简而言之,一个线性表是n个数元素的有限序列。至于每个数据元素的具体含义,在不同的情况下各有不同,可以是一个数字或一个符号,也可以是一本书,甚至其他更复杂的信息。
线性结构的特点:在数据元素的非空有限集中

  1. 存在唯一一个被称作“第一个”的数据元素。
  2. 存在唯一一个被称作“最后一个”的数据元素。
  3. 除第一个外,集合中的每个元素均只有一个前驱。
  4. 除最后一个之外 ,集合中的 每个数据元素均只有一个后继。
  5. 同一线性表中的元素必定具有相同的特性,即属同一数据对象。
  6. 相邻元素之间存在序偶关系。

数学语言定义线性表:
若将线性表记作:
( a 1 , . . . , a i − 1 , a i , a i + 1 , . . . , a n ) (a_1,...,a_{i-1},a_i,a_{i+1},...,a_n) (a1,...,ai1,ai,ai+1,...,an)
则表示 a i − 1 a_{i-1} ai1 领先于 a i a_i ai a i a_i ai 领先于 a i + 1 a_{i+1} ai+1 ,称 a i − 1 a_{i-1} ai1 a i a_i ai 的直接前驱元素, a i + 1 a_{i+1} ai+1 a i a_i ai 的直接后继元素。当 i = 1 , 2 , . . . , n − 1 i=1,2, ... , n-1 i=1,2,...,n1 时, a i a_i ai 有且只有一个后继元素,当 i = 2 , 3 , . . . , n i=2,3, ... ,n i=2,3,...,n 时, a i a_i ai 有且仅有一个直接前驱。
线性表中的元素个数 n ( n ≧ 0 ) n(n\geqq0) n(n0) 定义为线性表的长度, n = 0 n=0 n=0 时表示为空表。在非空表中的每个元素都有一个确定的位置,如 a 1 a_1 a1 是第一个数据元素, a n a_n an 是最后一个数据元素, a i a_i ai 是第 i i i 个数据元素,称 i i i 为数据元素 a i a_i ai 在 线性表中的位序。

线性表的顺序存储结构定义与实现:

线性表的顺序存储结构,指定是用一段地址连续的存储单元依次存储线性表的数据元素。

在这里插入图片描述
实现基于Linux 内核链表思想。

定义头文件声明数据结构与方法:

#ifndef  __MY_SEQLIST_H__ 
#define __MY_SEQLIST_H__


#define TRUE  1
#define FALSE 0


#define  SEQLIST_NULL_ERR     (100)
#define  SEQLIST_POS_ERR      (SEQLIST_NULL_ERR+1)
#define  SEQLIST_FULL_ERR     (SEQLIST_NULL_ERR+2)
#define  SEQLIST_LENGTH_ERR   (SEQLIST_NULL_ERR+3) 



typedef void SeqList; //定义线性表数据结构

typedef void SeqListNode; //定义线性表节点元素



/************************************************************************
  根据指定内存大小分配链表内存空间
  ----------------------------------------------------------------------
	参数		:int capacity  内存空间大小

	返回值	:SeqList* | NULL

************************************************************************/
SeqList* 
	SeqList_Create_null (int capacity);



/************************************************************************
 释放链表内存空间
------------------------------------------------------------------------
	参数   :SeqList* list  链表内存地址

	返回值 :void 

************************************************************************/
void 
	SeqList_Destroy (SeqList* list);


/************************************************************************
清除链表元素
------------------------------------------------------------------------
参数   :SeqList* list  链表内存地址

返回值 :void

************************************************************************/
void 
	SeqList_Clear (SeqList* list);


/************************************************************************
获取链表元素个数
------------------------------------------------------------------------
	参数   :SeqList* list

	返回值 :链表实际元素个数 | 0

************************************************************************/
int 
	SeqList_Length (SeqList* list);

/************************************************************************
获取链表空间字节大小
------------------------------------------------------------------------
	参数   :SeqList* list

	返回值 :链表实际空间大小 | 0

************************************************************************/
int 
	SeqList_Capacity (SeqList* list);


/************************************************************************
链表插入元素节点
------------------------------------------------------------------------
参数   :SeqList*      list      链表指针
		SeqListNode*  node      元素节点
		int           pos       插入元素位置

返回值 : 1 (TRUE) |  ERR  (Type)

************************************************************************/
int 
	SeqList_Insert (SeqList* list, SeqListNode* node, int pos);



/************************************************************************
获取链表指定位置元素
------------------------------------------------------------------------
参数   :SeqList*    list   链表指针
		int          pos    下标位置

返回值 :NULL | SeqListNode* 

************************************************************************/
SeqListNode* 
	SeqList_Get (SeqList* list, int pos);


/************************************************************************
删除链表指定位置的元素
------------------------------------------------------------------------
参数   :SeqList*    list   链表指针
		int          pos    元素下标位置

返回值 :NULL | SeqListNode*

************************************************************************/
SeqListNode* 
	SeqList_Delete (SeqList* list, int pos);


#endif  //__MY_SEQLIST_H__

实现方法:

#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
#include "SeqList.h"


/*线性表内部结构*/
typedef struct _SeqList
{
	//链表长度
	int length;
	//链表容量
	int capacity;
	//链表数据指针(存储元素地址集合)
	unsigned int **node; 
}TSeqList;


//创建链表
SeqList* SeqList_Create_null ( int capacity )
{
	TSeqList* temp = NULL;
	temp = (TSeqList*) malloc (sizeof (TSeqList));
	if (temp==NULL)
	{
		printf ("Function: SeqList_Create_null() err =%d ! \n", SEQLIST_NULL_ERR);
		return NULL;
	}

	memset (temp, 0x00, sizeof (TSeqList));//初始化内存

	temp->node = (unsigned int **) malloc (sizeof (unsigned int*)*capacity);
	if (temp->node==NULL)
	{
		printf ("Function: SeqList_Create_null() err =%d ! \n", SEQLIST_NULL_ERR);
		return NULL;
	}
	temp->length = 0;
	temp->capacity = capacity;

	return temp;
}



//释放链表空间
void SeqList_Destroy (SeqList* list)
{
	TSeqList * temp = NULL;
	if (list==NULL)
	{
		return;
	}

	temp = (TSeqList *) list;
	if (temp->node!=NULL)
	{
		free (temp->node);
		temp->node = NULL;
	}
	free (temp);
	temp = NULL;

	return;
}


//清空链表
void SeqList_Clear (SeqList* list)
{
	TSeqList* temp = NULL;
	if (list==NULL)
	{
		return;
	}
	temp = (TSeqList*) list;
	temp->length = 0;

}

//获取链表元素个数
int SeqList_Length (SeqList* list)
{
	TSeqList* temp = NULL;
	if (list==NULL)
	{
		return 0;
	}
	temp = (TSeqList*) list;
	return temp->length;
	
}

//获取链表空间大小
int SeqList_Capacity (SeqList* list)
{
	TSeqList* temp = NULL;
	if (list == NULL)
	{
		return 0;
	}
	temp = (TSeqList*) list;
	return temp->capacity;
}

//链表指定位置插入元素
int SeqList_Insert (SeqList* list, SeqListNode* node, int pos)
{
	int		     ret = 0, i = 0;
	TSeqList*    listTmp = NULL;

	if (list==NULL||node==NULL)
	{
		ret = SEQLIST_NULL_ERR;
		return ret;
	}
	
	listTmp = (TSeqList*) list;

	//判断链表是否已满
	if (listTmp->length >= listTmp->capacity)
	{
		ret = SEQLIST_FULL_ERR;
		return ret;
	}

	if (pos < 0 || pos>listTmp->capacity)
	{
		ret = SEQLIST_POS_ERR;
		return ret;
	}
	//容错修正 如果给定插入位置超出现有 length 则 pos = length
	if (pos>=listTmp->length)
	{
		pos = listTmp->length;
	}


	//元素向后移动
	for (i = listTmp->length; i < pos;i--)
	{
		listTmp->node[i] = listTmp->node[i - 1]; 
	}

	
	//元素插入
	listTmp->node[i] = node;
	listTmp->length++;//元素个数加1

	return TRUE;
}

//获取指定位置元素
SeqListNode* SeqList_Get (SeqList* list, int pos)
{
	int		     i = 0;
	TSeqList*    listTmp = NULL;
	SeqListNode* ret = 0;
	if (list==NULL)
	{
		printf ("Function: SeqList_Get() err =%d ! \n", SEQLIST_NULL_ERR);
		return NULL;
	}
	listTmp = (TSeqList*) list;
	if (pos < 0 || pos>listTmp->length)
	{
		printf ("Function: SeqList_Get() err =%d ! \n", SEQLIST_POS_ERR);
		return NULL;
	}
	ret = (SeqListNode*) ( listTmp->node[pos] );
	return ret;
}

//删除链表指定位置元素
SeqListNode* SeqList_Delete (SeqList* list, int pos)
{
	int		     i = 0;
	TSeqList*    listTmp = NULL;
	SeqListNode* ret = 0;
	if (list==NULL)
	{
		printf ("Function: SeqList_Delete() err =%d ! \n", SEQLIST_NULL_ERR);
		return NULL;
	}
	listTmp = (TSeqList*) list;
	if (pos<0||pos>=listTmp->length)
	{
		printf ("Function: SeqList_Delete() err =%d ! \n", SEQLIST_POS_ERR);
		return NULL;
	}
	ret = (SeqListNode*) listTmp->node[pos];
	for (i = pos + 1; i < listTmp->length;i++)
	{
		listTmp->node[i - 1] = listTmp->node[i];//元素向前移动
	}
	listTmp->length--;//元素个数减1

	return ret;
}

调用:

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SeqList.h"


typedef struct _User_info
{
	int age;
	char name[16];
}User;



int main (void)
{
	int ret = 0;
	int i = 0;
	User u1, u2, u3, u4, u5, u6;
	{
		u1.age = 11;
		u2.age = 12;
		u3.age = 13;
		u4.age = 14;
		u5.age = 15;
		u6.age = 16;
		strcpy (u1.name, "AAA");
		strcpy (u2.name, "BBB");
		strcpy (u3.name, "CCC");
		strcpy (u4.name, "DDD");
		strcpy (u5.name, "EEE");
		strcpy (u6.name, "FFF");
	}

	SeqList* list = NULL;
	list = SeqList_Create_null (10);
	if (list==NULL)
	{
		printf ("链表初始化失败!\n");
		return 0;
	}

	//插入
	ret = SeqList_Insert (list, (SeqListNode*) &u1, 0);
	ret = SeqList_Insert (list, (SeqListNode*) &u2, 1);
	ret = SeqList_Insert (list, (SeqListNode*) &u3, 2);
	ret = SeqList_Insert (list, (SeqListNode*) &u4, 3);
	ret = SeqList_Insert (list, (SeqListNode*) &u5, 4);
	ret = SeqList_Insert (list, (SeqListNode*) &u6, 5);

	//获取链表元素个数
	printf ("list 链表元素个数=%d \n", SeqList_Length (list));

	//遍历
	for (i = 0; i < SeqList_Length (list);i++)
	{
		User* u = (User*) SeqList_Get (list, i);
		if (u==NULL)
		{
			printf ("获取元素失败! %d\n",i);
			return 0;
		}

		printf ("age=%d ; name=%s \n", u->age, u->name);
	}

	//链表元素
	SeqList_Clear (list);
	//获取链表元素个数
	printf ("list 链表元素个数=%d \n", SeqList_Length (list));

	User u7, u8, u9, u10, u11, u12;
	{
		u7.age = 111;
		u8.age = 112;
		u9.age = 113;
		u10.age = 114;
		u11.age = 115;
		u12.age = 116;
		strcpy (u7.name, "MMM");
		strcpy (u8.name, "NNN");
		strcpy (u9.name, "QQQ");
		strcpy (u10.name, "YYY");
		strcpy (u11.name, "PPP");
		strcpy (u12.name, "LLL");
	}

	ret = SeqList_Insert (list, (SeqListNode*) &u7, 0);
	ret = SeqList_Insert (list, (SeqListNode*) &u8, 1);
	ret = SeqList_Insert (list, (SeqListNode*) &u9, 2);
	ret = SeqList_Insert (list, (SeqListNode*) &u10, 3);
	ret = SeqList_Insert (list, (SeqListNode*) &u11, 4);
	ret = SeqList_Insert (list, (SeqListNode*) &u12, 5);

	printf ("list 链表元素个数=%d \n", SeqList_Length (list));

	//遍历
	for (i = 0; i < SeqList_Length (list); i++)
	{
		User* u = (User*) SeqList_Get (list, i);
		if (u == NULL)
		{
			printf ("获取元素失败! %d\n", i);
			return 0;
		}

		printf ("age=%d ; name=%s \n", u->age, u->name);
	}

	//获取指定位置元素:

	User* up=(User*) SeqList_Get (list, 4);
	printf ("age=%d ; name=%s \n", up->age, up->name);

	//删除指定位置元素
	SeqList_Delete (list, 4);


	printf ("删除了元素后 list 链表元素个数=%d \n", SeqList_Length (list));

	SeqList_Destroy (list);

	if (list==NULL)
	{
		printf ("链表空间以释放!\n");
	}

	system ("PAUSE");

	return 0;
}

在这里插入图片描述

优点和缺点

优点:

  • 无需为线性表中的逻辑关系增加额外的空间
  • 可以快速的获取表中合法位置的元素

缺点:

  • 插入和删除操作需要移动大量元素
  • 当线性表长度变化较大时难以确定存储空间的容量
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值