详解顺序表

918 阅读9分钟

顺序表的定义及其特点;

定义

顺序表是一种线性表的存储结构,它由一组连续的存储空间组成,用于存储具有相同数据类型的元素。顺序表的特点是元素在内存中的物理位置是连续的,每个元素都可以通过下标来直接访问。

1. 数据元素:顺序表中的每个元素具有相同的数据类型,可以是基本数据类型(如整数、浮点数)或自定义的数据结构(如结构体)。
2. 存储空间:顺序表使用一段连续的存储空间来存储元素,通常是一块连续的内存区域。
3. 元素个数:顺序表中元素的个数是固定的,可以在初始化时指定最大容量,也可以动态调整大小。
4. 下标访问:顺序表中的每个元素都有一个唯一的下标,可以通过下标来直接访问和修改元素的值。
5. 元素顺序:顺序表中元素的顺序是有序的,即元素的插入和删除操作会影响其在顺序表中的位置。

顺序表的优点是随机访问效率高,可以快速定位和操作元素。但同时也存在容量限制和插入/删除元素时需要移动数据的缺点。因此,在选择数据结构时,需要根据实际需求来权衡使用顺序表的利弊。

特点

1. 随机访问:顺序表中的元素在内存中是连续存储的,因此可以通过下标直接访问元素。这种随机访问的特性使得查找、读取和修改元素的时间复杂度为O(1),即常数时间。相比于链表等其他数据结构,顺序表具有更高的访问效率。

2. 快速遍历:由于元素的连续存储,顺序表可以通过下标进行快速遍历。遍历顺序表只需要遍历整个数组,不需要进行指针的跳转操作,因此在需要频繁访问和修改元素的场景下,顺序表的遍历效率较高。

3. 固定容量:顺序表在初始化时需要指定最大容量,一旦达到容量限制,就无法再添加新的元素。这使得顺序表的空间利用率较高,且不会因为频繁地申请和释放内存而导致内存碎片问题。

4. 插入和删除效率低:由于顺序表的元素在内存中是连续存储的,当需要在中间位置插入或删除元素时,需要移动其他元素,导致时间复杂度为O(n),其中n为元素的个数。因此,在频繁插入和删除元素的场景下,顺序表的效率较低。

5. 操作简单:顺序表的操作相对简单,包括插入、删除、查找和遍历等。由于元素的随机访问特性,可以方便地对元素进行各种操作。

综上所述,顺序表具有随机访问和快速遍历的优点,适用于需要频繁访问和修改元素的场景。但由于固定容量和插入/删除效率低的限制,需要根据实际需求来选择合适的数据结构。

顺序表的运算

运算符 -> 也可用于选择结构或联合的成员,

C语言点运算符和箭头运算符 (biancheng.net)

顺序表是一种线性表的存储结构,可以进行一系列基本的运算操作,包括初始化、插入、删除、查找和遍历等。

结构

/*顺序表*/
typedef struct
{
	DataType data[MAXSIZE];
	int length;
}SeqList;

初始化

顺序表的初始化是指创建一个空的顺序表,即分配一定大小的内存空间,并将元素个数设为0。

/*顺序表初始化*/
int init(SeqList *L)
{
	L->length = 0;
	return 0;
}

插入

在顺序表中插入元素可以通过两种方式进行。一种是在指定位置插入元素,需要将插入位置后的元素依次后移,然后将新元素插入到指定位置。另一种是在末尾插入元素,只需要将新元素添加到顺序表的末尾即可。

/*插入元素*/
int insert(SeqList *L, int i, DataType x)
{
	int j;

	/*判断是否满*/
	if(full(L))
	{
		printf("Error[10001],顺序表已满!\n");
		return 10001;
	}
	/*判断位置i合法性*/
	if(i<1 || i>length(L)+1)
	{
		printf("位置i不合法!\n");
		return 10002;
	}

	/*移动元素,向后移动*/
	for(j=L->length;j>=i;j--)
	{
		L->data[j] = L->data[j-1];
	}
	L->data[j] = x;
	L->length++;
	return 0; /*ok!*/
}

删除

顺序表中的元素删除操作主要有两种方式。一种是删除指定位置的元素,需要将删除位置后的元素依次前移,然后将最后一个元素删除。另一种是删除指定值的元素,需要先查找到该元素的位置,然后再进行删除操作。
第n-1个往后挪

/*删除元素*/
int delete(SeqList *L, int i, DataType *x)
{
	/*判断位置i合法性*/
	if(i<1 || i>length(L)+1)
	{
		printf("Error[10002],位置i不合法!\n");
		return 10002;
	}
	int j; 
	for (j = i-1; j < L ->length; j++)
	{
		L->data[j] = L->data[j+1];
	}
	L->length--;
	return 0;
}

遍历

顺序表的遍历是指逐个访问顺序表中的元素。可以使用循环结构,按照下标依次访问顺序表中的元素,或者使用迭代器等方式进行遍历。

/*输出顺序表*/
void print(SeqList *L)
{
	int i;

	if(empty(L))
	{
		printf("顺序表为空!");
		return ;
	}
	printf("顺序表为:");
	for(i=0;i<L->length;i++)
	{
		printf(" %d ", L->data[i]);
	}
	printf("\n");
}

通过以上运算,可以实现对顺序表中元素的增删查改等操作,满足不同的业务需求。

顺序表的实现

完整代码

项目结构

手把手教你c语言如何引用自己的 .h 头文件

    main.c
    SeqList.c
    SeqList.h
    welcome.h

项目文件

C语言讲义——传值、传引用 - 虎老狮 - 博客园 (cnblogs.com)

SeqList.h

/*

	SeqList.h 顺序表定义
*/

#define MAXSIZE 1000
 
typedef int DataType;

/*顺序表*/
typedef struct
{
	DataType data[MAXSIZE];
	int length;
}SeqList;

/*顺序表初始化*/
int init(SeqList *L);

/*顺序表的长度*/
int length(SeqList *L);

/*顺序表是否满*/
int full(SeqList *L);

/*是否空*/
int empty(SeqList *L);

/*插入元素*/
int insert(SeqList *L, int i, DataType x);

/*删除元素*/
int delete(SeqList *L, int i, DataType *x);

/*输出顺序表*/
void print(SeqList *L);

SeqList.c

/*
	SeqList.c 顺序表实现
*/
#include "SeqList.h"


/*顺序表初始化*/
int init(SeqList *L)
{
	L->length = 0;
	return 0;
}


/*顺序表的长度*/
int length(SeqList *L)
{
	return L->length;
}

/*顺序表是否满*/
int full(SeqList *L)
{
	return (L->length == MAXSIZE)?1:0;
}

/*是否空*/
int empty(SeqList *L)
{
	return (L->length == 0)?1:0;
}

/*插入元素*/
int insert(SeqList *L, int i, DataType x)
{
	int j;

	/*判断是否满*/
	if(full(L))
	{
		printf("Error[10001],顺序表已满!\n");
		return 10001;
	}
	/*判断位置i合法性*/
	if(i<1 || i>length(L)+1)
	{
		printf("位置i不合法!\n");
		return 10002;
	}

	/*移动元素,向后移动*/
	for(j=L->length;j>=i;j--)
	{
		L->data[j] = L->data[j-1];
	}
	L->data[j] = x;
	L->length++;
	return 0; /*ok!*/
}


/*删除元素*/
int delete(SeqList *L, int i, DataType *x)
{
	/*判断位置i合法性*/
	if(i<1 || i>length(L)+1)
	{
		printf("Error[10002],位置i不合法!\n");
		return 10002;
	}
	int j; 
	for (j = i-1; j < L ->length; j++)
	{
		L->data[j] = L->data[j+1];
	}
	L->length--;
	return 0;
}

/*输出顺序表*/
void print(SeqList *L)
{
	int i;

	if(empty(L))
	{
		printf("顺序表为空!");
		return ;
	}
	printf("顺序表为:");
	for(i=0;i<L->length;i++)
	{
		printf(" %d ", L->data[i]);
	}
	printf("\n");
}

welcome.h

char welcome[] = "welcome";

main.c

#include <stdio.h>
#include "SeqList.h"
#include <string.h>
#include "welcome.h"

int main(int argc, char* argv[])
{
	SeqList L;
	int cmd;
	int i;
	int m,n;

	DataType x;
	
	for(i=0;i<strlen(welcome);i++)
	{
		printf("%c",welcome[i]);
		for(m=0;m<10000;m++)
			for(n=0;n<1000;n++)
			{
				;
			}
	}
	printf("\n\n\n");
	printf("-----------顺序表演示程序----------\n");
	do
	{
		printf("1. 初始化顺序表\n");
		printf("2. 插入元素\n");
		printf("3. 删除元素\n");
		printf("4. 判断顺序表是否为空\n");
		printf("5. 判断顺序表是否满\n");
		printf("6. 输出顺序表\n");
		printf("10. 帮助\n"); 
		printf("0. 退出\n");
		printf("请输入您要进行的操作(1~6,0退出):");
		scanf("%d", &cmd);
		switch(cmd)
		{
		case 1:
			if(!init(&L))
			{
				printf("顺序表已初始化!\n");
			}
			break;
		case 2:
			printf("请输入位置i,插入元素x(i,x):");
			scanf("%d,%d",&i,&x);
			if(!insert(&L,i,x))
			{
				printf("元素(%d)已插入位置[%d]\n",x, i);
			}
			break;
		case 3:
			printf("请输入位置i,删除元素x(i):");
			scanf("%d",&i);
			
			if(!delete(&L,i,x))
			{
				printf("元素(%d)删除位置[%d]\n",x, i);
			}
			break;
		case 4:
			if(!empty(&L))
			{
				printf("顺序表不为空!\n");
			}
			else
			{
				printf("顺序表为空!\n");
			}
			break;
		case 5:
			if(full(&L))
			{
				printf("顺序表已满!\n");
			}
			else
			{
				printf("顺序表未满!\n");
			}
			break;
		case 6:
			print(&L);
			break;
		case 10:
			printf(" 本程序为顺序表的演示程序,有XXX设计开发,程序完成了。。。。功能!。。。\n");
			break;
			
		}
	}while(cmd != 0);

	return 0;
}

执行结果

image.png

image.png

image.png

小结

顺序表是一种基本的线性表数据结构,它以连续的内存空间存储元素,并通过下标进行访问。以下是顺序表的一些特点和总结:

优点

1. 随机访问:由于元素在内存中的连续存储,顺序表支持通过下标直接访问元素,访问效率高,时间复杂度为O(1)。
2. 快速遍历:顺序表可以通过下标进行快速遍历,适用于需要频繁访问和修改元素的场景。
2. 适合读取操作:由于顺序表的随机访问特性,它适合读取操作频繁的场景,例如按照下标快速访问元素。

缺点

1. 固定容量:顺序表在创建时需要指定最大容量,空间利用率高,但容量不可动态调整。
2. 插入和删除效率低:在顺序表的中间位置插入或删除元素时,需要移动其他元素,效率较低,时间复杂度为O(n)。
3. 不适合频繁插入和删除:由于插入和删除操作需要移动其他元素,顺序表不适合频繁插入和删除操作的场景。

总之,顺序表是一种简单且常见的数据结构,适用于需要频繁访问和修改元素的场景。它具有快速随机访问和遍历的优点,但在插入和删除操作上效率较低。在实际应用中,根据具体需求和操作的频率,可以选择合适的数据结构来提高效率和满足需求。

参考文献

  1. ora.ai
  2. C语言点运算符和箭头运算符 (biancheng.net)