C数据结构线性表:实现顺序表的增删改查&完整篇

①前言

1:大家在观看的过程中不必纠结我的变量名,都是用英语对应功能意思,应该都是比较好理解。
2:就是我的顺序表是全局变量,你完全可以在main函数里面进行定义,在本代码程序中,运行结果没有任何区别,因为我的函数都是考虑到大家的定义变量位置不同,所以每一个函数我都带了顺序表的参数。
3:删除功能的部分有两个函数,one第一个是删除在顺序表中最先找到与你要删除的相同的一个元素,two第二个函数是把顺序表中找到所有的与你要删除的相同的元素进行删除。其实就是第一个函数是不管后面有没有多个重复与你要删除的元素。

顺序表结构体的定义

结构体中lenth表示整一个顺序表的长度,不是从0开始的长度,因为这个以后可能会给自己或者用户看的。

typedef struct _Link{
	int *elem;
	int lenth;//顺序表长度 
}Link;

②初始化顺序表

MAX_LEN表示为顺序表能够存储的最大空间长度
使用动态分配内存空间,我认为这样方便我们日后需要的时候去修改,只要修改MAX_LEN就可以改变空间大小
!如果你觉得宏定义还不够灵活,你想要自己录入空间,那你就直接把宏定义改成全局变量!

void Init_Link(Link *L)
{
	int i;
	
	L->elem = (int*)malloc(MAX_LEN*sizeof(int));
	L->lenth = MAX_LEN/2; //假设现需存放最大空间的一半的顺序表长度 
	for(i = 0; i < L->lenth; i++) L->elem[i] = i+1;//初始化内容 
	
}

③插入新的元素

插入的时候需要特别注意的几点

1:当你要删除的元素为最后一个的时候直接把顺序表的长度减一
2:在使用元素下标的时候必须要特别的小心谨慎,一不小心就会导致下标越界或者运行的结果不尽人意。

注:第一个参数是你要插入在顺序表中哪个一个下标位置,第二个参数就是要操作的顺序表,第三个是你要插入的元素。

void Insert_Link(int putindex, Link *L, int putelem)
{
	int i;
	if(putindex > L->lenth+1 || putindex <= 0) 
	{
		PF(不能插入该位置!);
		return; 
	}
	if(L->lenth >= MAX_LEN)
	{
		PF(空间已满,插入失败!);//判断是否还有空间能插入 
		return; 
	} 
	if(putindex == L->lenth+1)//若想要插入的位置为尾部,那直接把这个元素插进最后就行
	{
		L->elem[L->lenth] = putelem; 
		L->lenth++;//长度加一 
		return; 
	 }
	 else
	 {
	 	 for(i = L->lenth; i > putindex-1; i--)
		{
			L->elem[i] = L->elem[i-1];//putindex这个位置和它之后的元素全部往后移动一个空间  
		}
		L->elem[putindex-1] = putelem;//插入元素 
		L->lenth++;//长度加一 
	  }
	 
}

④删除元素

两个函数的区别我在前言的时候说过了,还要提醒的是切记切记用元素下标的时候一定要谨慎谨慎再谨慎。

第一个删除元素功能实现

第一个是在顺序表中第一个找到你要删除的那个元素进行删除,不管后面是否还重复出现要删除的元素。这个比较简单,就是找到删除元素后直接把该元素位置和后面元素都往前移动一步,最后再把元素的长度减一。

void Delete_Link_one(int index, Link *L)
{
	int i;
	if(index > L->lenth || index <= 0)
	{
		PF(该位置不能删除!);
		return; 
	}
	else 
	{
		 for(i = index-1; i < L->lenth-1; i++)//L->lenth减一是因为下面我要i+1进行赋值,不然会导致越界 
		{
			L->elem[i] = L->elem[i+1];
		}
		L->lenth--;//长度减一 
	} 
	
}

第二个删除元素功能实现

第二个功能就相对于第一个就上升了一点点难度,其实就是下标会比较让人觉得烦躁,只要你捋清楚了下标是对应哪个,能够准确无误的让数组按照你的想法进行就完全能理解到位了。

对代码下面中**i- -**的说明(第二个删除函数)

因为你进来if语句的时候是为了删除该下标的元素,删除完成后该下标已经不是你要删除的元素了,而是后面赋值上来的新的元素。因为当你跳出这个if语句之后下面有一个i++,所以为了使其下标回到刚进来 i 的那个位置,先进行i- -出去之后再i++,毕竟你还要继续进行判断该位置下新的赋值过来的元素是否和你要删除元素一样,这函数就是要删除掉和你要删除元素一样的所有重复元素

void Delete_Link_two(int D_elem, Link *L)
{
	int i = 0, j;
	while(1)
	{
		if(i == L->lenth-1 && L->elem[i] == D_elem)//当需要删除的元素是最后一个的时候直接把长度减一就好 
		{
			L->lenth--;
		}
		if(L->elem[i] == D_elem && i < L->lenth-1)
		{
			 for(j = i; j < L->lenth-1; j++)//L->lenth-1是因为下面我要对i+1进行赋值,不然会导致越界 
			{
				L->elem[j] = L->elem[j+1];
			}
			L->lenth--;//长度减一
			i--;//在文章中有特别对该部分进行详细讲解原因
			 
		}
		i++;
		if(i > L->lenth) break;
	}
 } 

⑤查找某一个元素,并打印其下标

查找元素就基本没什么好说的了,属于比较容易理解的部分。原理就是当你在顺序表中找到与你查找的那个元素的时候,直接返回他的下标就行,这个函数有个局限性,就是只能在顺序表中找到第一个相同的那个返回其下标,这个找到这个元素后,顺序表往后的就不找了。

void Find_Link_elem(int elem, int *index, Link *L)
{
	int i;
	for(i = 0; i < L->lenth-1; i++)
	{
		if(elem == L->elem[i])
		{
			*index = i+1;
			return;
		}
	 }
	 if(i == L->lenth-1) PF(不存在该元素!\n);
} 

⑥清空顺序表

有时候我们对顺序表中的内容没有作用了的时候,这时候就需要把顺序表中的内容清空,再存储其他内容信息。清空操作也很简单,就不继续赘述了。

void Clear_Link(Link *L)
{
 	int i;
	for(i = 0; i < L->lenth; i++) L->elem[i] = 0;
	L->lenth = 0;//长度记为0 
} 

⑦销毁顺序表

因为我们的顺序表是通过动态分配出来的,我们不需要的时候要及时的销毁掉,***在程序结束前养成习惯,需要对分配在栈上的空间释放掉。***这个也比较简单,也不赘述了。

void Destroy_Link(Link *L)
 {
 	free(L->elem);//直接释放顺序表开辟的空间
	L = NULL;//指针直接指向空,完全把顺序表销毁掉 
 }

总:附上源代码

源代码中有一些是我自己加的函数,也不难理解,都是为了测试运行结果而打包成函数的。
打印PF那个也不用纠结,我只是用宏定义换了一个我习惯用的方式来打印而已。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdbool.h>
#define MAX_LEN 10
#define PF(format, ...) printf(#format, ##__VA_ARGS__)
/*
	线性表的基本操作 
*/ 

typedef struct _Link{
	int *elem;
	int lenth;//顺序表长度 
}Link;


Link L;//在本代码程序中,顺序表作为全局变量或者在main函数里面定义没有区别 

bool IsEmpty(Link);//判断顺序表是否为空 

void Init_Link(Link *);//初始化顺序表 

void Destroy_Link(Link *);//销毁顺序表 
 
void Clear_Link(Link *);//清空顺序表内容 即全部赋值为某一个特殊标志,如int数组全部赋值为 0 
 
void Insert_Link(int putindex, Link *, int putelem);//在第一个参数putindex下标位置下,顺序表插入新元素 putelem

void P_Link(Link *);//打印顺序表内容 

void Delete_Link_one(int index, Link*);//删除下标为index的元素 

void Delete_Link_two(int D_elem, Link*);//删除传进的这一个元素,若顺序表有 重复元素则相同的也全部删除 

void Find_Link_elem(int, int *index, Link *);//寻找一个元素 ,找到第一个与他相同的元素,并返回下标给 index

int main(void)
{
//	Link L;
	int index = -1;//找到想要的元素后,用来接收该元素在顺序表中的下标 
	Init_Link(&L);//初始化顺序表 
	P_Link(&L);
	PF(************************************************\n);
	Insert_Link(1, &L, 4);
	if(IsEmpty(L)) P_Link(&L);
	PF(************************************************\n);
	Delete_Link_one(4, &L);
	if(IsEmpty(L)) P_Link(&L);
	PF(************************************************\n);
	Delete_Link_two(4, &L);
	if(IsEmpty(L)) P_Link(&L);
	
	Find_Link_elem(5, &index, &L);
	if(index != -1) PF(元素下标为:%d\n, index); 
	return 0;
 } 
 

bool IsEmpty(Link L)
{
	if(L.lenth == 0)
	{
		PF(顺序表为空(NULL);
		return false;
	}
	else if(L.lenth > 0)
	{
		return true;
	}
	 
 } 

void Init_Link(Link *L)
{
	int i;
	
	L->elem = (int*)malloc(MAX_LEN*sizeof(int));
	L->lenth = MAX_LEN/2; //现在存放顺序表长度 
	for(i = 0; i < L->lenth; i++) L->elem[i] = i+1;//初始化内容 
	
}

void Destroy_Link(Link *L)
 {
 	free(L->elem);//直接释放顺序表开辟的空间
	L = NULL;//指针直接指向空,完全把顺序表销毁掉 
 }
 
void Clear_Link(Link *L)
{
 	int i;
	for(i = 0; i < L->lenth; i++) L->elem[i] = 0;
	L->lenth = 0;//长度记为0 
} 
 
void Insert_Link(int putindex, Link *L, int putelem)
{
	int i;
	if(putindex > L->lenth+1 || putindex <= 0) 
	{
		PF(不能插入该位置!);
		return; 
	}
	if(L->lenth >= MAX_LEN)
	{
		PF(空间已满,插入失败!);//判断是否还有空间能插入 
		return; 
	} 
	if(putindex == L->lenth+1)//若想要插入的位置为尾部,那直接把这个元素插进最后就行
	{
		L->elem[L->lenth] = putelem; 
		L->lenth++;//长度加一 
		return; 
	 }
	 else
	 {
	 	 for(i = L->lenth; i > putindex-1; i--)
		{
			L->elem[i] = L->elem[i-1];//putindex这个位置和它之后的元素全部往后移动一个空间  
		}
		L->elem[putindex-1] = putelem;//插入元素 
		L->lenth++;//长度加一 
	  }
	 
}
 
void P_Link(Link *L)
{
	int i;
	for(i = 0; i < L->lenth; i++)
	{
		PF(%d\t, L->elem[i]);
	}
	putchar('\n');
}
 
void Delete_Link_one(int index, Link *L)
{
	int i;
	if(index > L->lenth || index <= 0)
	{
		PF(该位置不能删除!);
		return; 
	}
	else 
	{
		 for(i = index-1; i < L->lenth-1; i++)//L->lenth减一是因为下面我要i+1进行赋值,不然会导致越界 
		{
			L->elem[i] = L->elem[i+1];
		}
		L->lenth--;//长度减一 
	} 
	
}

void Delete_Link_two(int D_elem, Link *L)
{
	int i = 0, j;
	while(1)
	{
		if(i == L->lenth-1 && L->elem[i] == D_elem)//当需要删除的元素是最后一个的时候直接把长度减一就好 
		{
			L->lenth--;
		}
		if(L->elem[i] == D_elem && i < L->lenth-1)
		{
			 for(j = i; j < L->lenth-1; j++)//L->lenth-1是因为下面我要对i+1进行赋值,不然会导致越界 
			{
				L->elem[j] = L->elem[j+1];
			}
			L->lenth--;//长度减一
			i--;
			 
		}
		i++;
		if(i > L->lenth) break;
	}
 } 
 
void Find_Link_elem(int elem, int *index, Link *L)
{
	int i;
	for(i = 0; i < L->lenth-1; i++)
	{
		if(elem == L->elem[i])
		{
			*index = i+1;
			return;
		}
	 }
	 if(i == L->lenth-1) PF(不存在该元素!\n);
} 
 
posted @ 2022-04-30 16:51  竹等寒  阅读(156)  评论(0编辑  收藏  举报  来源