【C语言数据结构】之顺序表

一、基础知识

  • 表中的元素具有线性关系,我们称之为线性表,有唯一的第一个元素和最后一个元素。
  • 除了第一个元素和最后一个元素,其余每个元素都有唯一的前驱和后继。
  • 我们称这些元素为结点。

线性表通常有两种实现方式,顺序表和链表,这篇文章主要讲解顺序表

二、什么是顺序表

  • 将线性表中的元素按照逻辑顺序关系,依次存储在地址连续的存储空间中,通常是使用数组来实现。
  • 顺序表在逻辑和物理上都是连续的。
  • 支持随机访问,因为存储在数组中,所以他可以通过索引来访问结点。
  • 顺序存储的优点是支持随机访问,他的缺点是在开辟的时候内存大小已经确定,后期更改的话需要重新分配内存空间。

三、顺序表的实现

1. 初始化

定义一个结构体SeqList用来存储结点中的信息并且设置好需要用到的宏定义。

# define Size 5
# define True 1
# define False 0
typedef struct SeqList
{
	int* data;
	int count;//当前表中元素
	int cap;//元素最大个数
}List;

void InitList(List* p)
{
	List* p->data = (int*)malloc(sizeof(int)*Size);
	if(p->data == NULL)
	{
		//开辟失败
		exit(1);
	}
	memset(p->data,0,sizeof(int)*Size);//使用memset函数初始化这段空间
	p->count = 0;
	p->cap = Size;
}
  • memset函数包含在头文件string.h中,用来初始化。

2. 销毁

void DestroyList(List* p)
{
	assert(p);//assert宏判断是否为真,不为真终止程序,这里用来判断p是否存在
	free(p->data);
	p->data = NULL;//安全措施,虽然free掉了,但是避免悬挂指针的存在
	p->cap = 0;
	p->count = 0;
}
  • assert宏判断是否为真,不为真终止程序,这里用来判断p是否存在
  • 虽然free掉了p->data,但是为了安全还是要将p->data指向空,避免悬挂指针的出现。

3. 判断空,满

int IsEmpty(List* p)
{
	assert(p);
	if(p->count == 0)
	{
		printf("空表\n");
		return True;
	}
	return False;
}
int IsFull(List* p)
{
	assert(p);
	if(p->count == p->cap)
	{
		return True;
	}
	return False;
}
  • 是空是满返回True,不空不满返回False,开头有宏定义。

4. 清空表

void ClearList(List* p)
{
	if(IsEmpty(p) == True)
	{
		printf("空表啊,清空个der~\n");
		return;
	}
	memset(p->data,0,sizeof(int)*Size);
	p->count =0;
}
  • 把表清空就是将所有元素置为空,然后计数器为0。

5. 打印表

void PrintList(List* p)
{
	if(IsEmpty(p) == True)
	{
		printf("空表打印个der~\n");
		return;
	}
	int i;
	for(i=0;i<p->count;i++)
	{
		printf("%d ",p->data[i]);
	}
	putchar('\n');
}

6. 头插

头插

void InsertHead(List* p,int num)
{
	if(IsFull(p) == True)
	{
		printf("满了满了,塞不进来了\n");
		return;
	}
	int i = p->count;
	for(i;i>0;i--)
	{
		p->data[i] = p->data[i-1];
	}
	p->data[0] = num;
	p->count++;
}

7. 尾插

尾插
尾插很简单,数组不满,直接将元素放在最后一个位置就行

void InsertBack(List* p,int num)
{
	if(IsFull(p) == True)
	{
		printf("满了满了,别插了\n");
		return;
	}
	p->data[p->count] = num;
	p->count++;
}

8. 指定位置插入

指定位置插入

void InsertPosition(List* p,int num,int index)
{
	if(IsFull(p) == True)
	{
		printf("满了满了,别插了\n");
		return;
	}
	int i = p->count;
	if(index<0||index>(p->count-1))
	{
		printf("下标错误\n");
		return;
	}
	for(i;i>index;i--)
	{
		p->data[i] = p->data[i-1];
	}
	p->data[index] = num;
	p->count++;
}

9. 头删

头删

void PopHead(List* p)
{
	if(IsEmpty(p) == True)
	{
		printf("空的删鸡毛诶~\n");
		return;
	}
	int i;
	for(i = 0;i<p->count;i++)
	{
		p->data[i] = p->data[i+1];
	}
	p->count--;
}

10. 尾删

尾删就简单了,直接让最后一个元素为空就行了。

void PopBack(List* p)
{
	if(IsEmpty(p) == True)
	{
		printf("空的哥,服啦\n");
		return;
	}
	p->data[p->count-1] =NULL;
	p->count--;
}

11.指定元素删除

在这里插入图片描述

void PopNum(List* p,int num)
{
	if(IsEmpty(p) == True)
	{
		printf("空的哥,服啦\n");
		return;
	}
	int i,j,k;
	k = p->count;
	for(i=0;i<p->count;i++)
	{
		if(p->data[i] == num)
		{
			for(j = i;j<p->count;j++)
			{
				p->data[j] = p->data[j+1];
			}
			p->count--;
		}
	}
	if(p->count == k)//k保留之前的长度,如果长度不变,说明没有删除任何元素,那么就是没找到这个num元素。
	{
		printf("没找到这个元素\n");
	}
}

12.指定位置删除

和根据元素删除很相似,找到这个位置后,后面向前覆盖就行。

void PopIndex(List* p,int index)
{
	if(IsEmpty(p) == True)
	{
		printf("空的哥,服啦\n");
		return;
	}
	if(index<0||index>=p->count)
	{
		printf("下标错误\n");
		return;
	}
	int i;
	for(i = index;i<p->count;i++)
	{
		p->data[i] = p->data[i+1];
	}
	p->count--;
}

13.指定位置更改元素

在顺序表中,指定位置更改只需要把这个下标的元素换一下就OK,非常简单

void ChangeIndex_Num(List* p,int index,int num)
{
	if(index<0||index>=p->count)
	{
		printf("下标错误\n");
		return;
	}
	p->data[index] = num;
}

14.指定元素更改

逻辑是从前向后遍历,如果找到这个元素就更改。

void ChangeNum_Num(List*p,int num;int new)
{
	int i,flag;
	flag = False;
	for(i = 0;i<p->count;i++)
	{
		if(p->data[i] == num)
		{
			p->data[i] == new;
			flag = True;
		}
	}
	if(flag == False)
	{
		printf("没找到这个元素\n");
	}
}

15. 查找元素下标

逻辑是从前向后遍历,找到了就返回下标。

int SearchNum_Index(List* p,int num)
{
	int i;
	for(i =0;i<p->count;i++)
	{
		if(p->data[i] == num)
		{
			return i;
		}
	}
}

16.根据下标查找元素

逻辑是直接返回这个下标的元素就行,数组有可以通过下标直接访问的特性。

int SearchIndex_Num(List* p,int index)
{
	//判断下标是否超出,懒得判断了
	return p->data[index];
}

四、总结

  • 数据结构无非就是增删改查,顺序表的本质是数组,就是在操作数组。
  • 牢记数组三大特性:访问有序性,存储连续性,类型一致性。
  • 在进行指定位置的增加和删除的时候,一定要注意元素覆盖的顺序,一定要避免将元素丢失和覆盖。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

LiuJWHHH

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

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

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

打赏作者

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

抵扣说明:

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

余额充值