详解顺序表 数据结构

 1.定义

什么是顺序表

顺表是一种线性结构,它使用一段连续的物理地址存储单元来存储数据元素,并一般采用数组的形式进行存储和操作。顺序表可以轻松地进行数据的插入、删除、查找和修改操作。通过使用数组实现,顺序表充分利用了数组的随机访问特性,使得操作效率较高。顺序表的操作主要涉及到对数组的插入和删除操作时,需要移动元素的位置,以保持顺序表的连续性。此外,顺序表的长度可以动态调整,可以根据实际需求进行扩容或缩容。

2.顺序表的特点:

1.顺序,并且连续,访问方便;

2.大小固定;

3.表满不能存,表空不能取

根据顺序表的特点,可以体现出顺序表的优缺点:

优点:访问方便

缺点:插入、删除不方便,需要移动元素。

常见的线性表基本运算( ):

  1. InitList(L):构造一个空的线性表L,即表的初始化。
  2. ListLength(L):求线性表L中的节点个数,即求表长。
  3. GetNode(L,i):求线性表第i个节点,1<=i<=ListLength(L)
  4. LocateNode(L,x):在L中查找值为x的结点,并返回x在L中的位置。若L中没结点的值为x,则返回一个特殊值表示查找失败。
  5. InsertList(L,x,i):在表L的第i个位置上插入一个值x的结点。
  6. DeleteList(L,i):删除线性表L的第i个结点.

顺序表的类型定义:

typedef struct
{
  int data[ListSize]; //数组data用于存放表节点,ListSize表示数组大小
  int length;         //表示当前表长度
}SeqList;             //结构体类型

注意:线性表元素的逻辑序号是从1开始的,而对应顺序表的data[]数组下标是从0开始的(物理序号)

在这里插入图片描述

地址的计算方法:


假设线性表中所有结点类型相同,每个结点占用存储空间大小亦相同。假设每个结点占用c个存储单元,其中第一个单元的存储地址则是该结点的存储地址,并设开始结点a1的存储地址是          LOC(a1),那么结点a i的存储地址LOC(a i)可通过下式计算:
LOC(ai)=LOC(a1)+(i-1)*c (1≤i≤n)
例如:已知LOC(a1)为100,每个结点占用4个存储单元,LOC(a4)为112。具
体描述如图所示。

3.顺序表基本运算:

1.插入:

线性表的插入运算是指在表的第i(1<=i<=n+1)个位置上,插入一个新节点x,使长度为n的线性表变成长度为n+1的线性表。

顺序表插入操作过程:将表中位置为n上的结点,依次后移到位置n+1上,空出第个位置,然后在该位置上插入新结点x。仅当插入位置i=n+1时,才无须移动结点,直接将x插入表的末尾。
具体算法描述如下:

void InsertList(SeqList *L, DataType x, int i)

{//将新结点x插入L所指的顺序表的第i个结点a的位置上

int j;
if(i<1||li>L->length+1)
Error("position error");   //非法位置退出运行
if(L->length>=ListSize)
Error("overflow");         //表空间溢出退出运行

for(j=L->length-1;j>=i-1;j--)

L->data[j+1]=L->data[j];  //节点后移
L->data[i-1]=x;           //插入X
L->length++;              //表长+1
}

用尾插法建立带头节点的单链表算法如下:


LinkList CreatList()
{
char ch;
ListNode *head=(ListNode *)malloc(sizeof(ListNode);//生成头节点
ListNode *s,*r;    //工作指针
r=head;   //尾指针初值也指向头结点
while(ch=-getchar0)!=\n')
{
s=(ListNode*)malloc(sizeof(ListNode));//生成新结点,第①步
s->data=ch;  //将读入的数据放入新结点的数据域中,第②步
r->next=s;//第③步
r=s;      //第④步
}
r->next-NULL; //终端结点的指针域置空,或空表的头结点指针域置空
return head;
}

 插入运算:
插入运算是将值为x的新结点插入到表的第i个结点的位置上,即插入到ar1与a;之间。

步骤:①找到ai1存储位置po

②生成一个数据域为x的新结点s。

③新结点的指针域指向结点 aio

④ 令结点p的指针域指向新结点。

插入过程如图所示。

 

2.删除:

线性表的删除运算是指将表的第i(1≤i≤n)个结点删去,使长度为n的线性表变成长度为n-1的线性表。

顺序表删除操作过程:若i一n,则只要简单地删除终端结点,无须移动结点;若l≤i≤n-1,则必须将表中位置i1,i+2,…,n的结点,依次前移到位置i,i1,……,n-1上,覆盖前一个结点,相当于删除第i个结点。

具体算法描述如下:

void DeleteList(SeqList *L,int i)
{/从L所指的顺序表中删除第i个结点aj
int j;
if(i<1||i>L->length)
    Error("position error");//非法位置
for(j=i;j<=L->length-l;j++)
    L->data[j-1]-L->data[j];//结点前移
L->length--;                //表长减小
}


3.删除运算
删除运算是将表的第i个结点删去。步骤:

①找到a(i-1)的存储位置p.

②让r指向ai,方便释放。

③令p->next 指向ai的直接后继结点,跨过ai结点。

④通过执行 free(r)释放节点ai的空间,节省内存空间。

删除过程如图所示。

 4.修改

【代码思路】: 要实现修改数据,我们只需要先判断输入下标是否合法。在将对应下标数据进行修改即可。

void SLModify(SL* ps, int pos, SLDateType x)
{
	assert(ps);
	assert(pos >= 0 && pos < ps->size);
	ps->a[pos] = x;
}
演示1:

代码如下:
#include <stdio.h>
#include <stdlib.h>

#define MAXSIZE 1000

/*顺序表的定义*/
typedef struct list
{
	int data[MAXSIZE];	/*存储空间,数组*/
	int length;			/*顺序表的长度*/
}SeqList;

int main(int argc, char* argv[])
{
	SeqList L;  /* 声明了一个顺序表L */
	int i, j, k;
	int x;

	/*初始化*/
	L.length = 0;
	printf("顺序表L初始化完成。\n");
	
	printf("1. 插入5个元素\n");
	/*插入一些元素, 采用尾插法,新插入元素放在最后*/
	for(i=0;i<5;i++)
	{
		printf("\t[%d].", i+1);
		scanf("%d", &x);
		/*尾插法*/
		L.data[L.length] = x;
		L.length++;
	}
	
	printf("输出顺序表L\n");

	for(i=0;i<L.length;i++)
	{
		printf("L(%d) = %d\n", i+1, L.data[i]);
	}
	
	printf("2. 在指定位置插入元素x\n");
	printf("请输入位置k:");
	scanf("%d", &k);
	printf("请输入元素x:");
	scanf("%d", &x);
	printf("正在检查位置k合法性...\n");

	if(k<1 || k>L.length+1)
	{
		printf("位置k不合法!\n");
		return 0;
	}
	printf("位置k检查结束,插入元素【%d】...\n", x);
	
	j=0;
	for(i=L.length;i>=k;i--)
	{
		j++;
		L.data[i] = L.data[i-1];
	}
	printf("  移动元素%d个\n", j);
	L.data[i] = x;
	L.length++;

	printf("输出新的顺序表L\n");

	for(i=0;i<L.length;i++)
	{
		printf("L(%d) = %d\n", i+1, L.data[i]);
	}

	printf("删除顺序表L第k个元素\n");
	printf("请输入位置k:");
	scanf("%d", &k);
	
	printf("正在检查位置k合法性...\n");

	if(k<1 || k>L.length)
	{
		printf("位置k不合法!\n");
		return 0;
	}
	printf("位置k检查结束,开始删除...\n");
	/*移动元素*/
	for(i=k;i<L.length;i++)
	{
		L.data[i-1] = L.data[i];
	}
	L.length--;

	printf("输出新的顺序表L\n");

	for(i=0;i<L.length;i++)
	{
		printf("L(%d) = %d\n", i+1, L.data[i]);
	}
    system("pause");
	return 0;
}
演示2:

代码如下:
#include <stdio.h>
#include "SeqList.h"
#include "welcom.h"
#include <stdlib.h>
#include <string.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 5:
			if(full(&L))
			{
				printf("顺序表已满!\n");
			}
			else
			{
				printf("顺序表未满!\n");
			}
		case 6:
			print(&L);
			break;
		case 10:
			printf(" 本程序为顺序表的演示程序,有XXX设计开发,程序完成了。。。。功能!。。。\n");
			break;
			
		}
	}while(cmd != 0);
    system("pause");


	return 0;
}
2.SeqList.c

目录

 1.定义

2.顺序表的特点:

常见的线性表基本运算( ):

顺序表的类型定义:

地址的计算方法:

​编辑

3.顺序表基本运算:

1.插入:

2.删除:

​编辑

 4.修改

演示1:

代码如下:

演示2:

代码如下:

2.SeqList.c

3.SeqList.h

4.welcom.h

作者声明:


3.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  delete1(SeqList *L, int i, DataType *x);

/*输出顺序表*/
void print(SeqList *L);
4.welcom.h
char welcome[] = "\
           /\ \
          ( *)======/\==== \
           )(      /  \ \
__________/  )    /    \ \
\___         /   / \"\"   \ \
  \____    _/   / (**)   \ \
     / \__/    (----------) \
    /____|__//_ ( 送给您- ) \
         |      ( 亲爱的 ) \
         |       (      )\
         |        (____)\
        _|__\
         \\    ☆新年 . 快乐☆";

作者声明:

以上内容作用于作业,内容质量仅供参考。文章代码纯手搓,参考自数据结构(C语言版)

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

菜鸟启动

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

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

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

打赏作者

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

抵扣说明:

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

余额充值