服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C语言动态顺序表实例代码

C语言动态顺序表实例代码

2022-07-19 10:18bitzhan C/C++

大家好,本篇文章主要讲的是C语言动态顺序表实例代码,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览

顺序表概念:

        顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构。一般情况下用数组存储。在数组上完成数据的增删查改。

代码解析:

 

一.准备工作

1. 首先对一些头文件的引用和创建一个结构体,结构体包含一个数组,size表示该数组目前有多少个元素,capacity表示目前数组能存多少个元素。例如:

 C语言动态顺序表实例代码

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<assert.h>

typedef int DataType;
typedef struct SeqList
{
	DataType* a;
	int size;
	int capacity;
}SL;

2.创建一个顺序表

SL sl;

 

二、顺序表的基本操作 

1.顺序表的初始化函数

         注意这里的参数得是指针,形参是实参的一份临时拷贝,所以得把地址传给函数才能改变值。

void SeqListInit(SL* sl)
{
	sl->a = NULL;
	sl->size = 0;
	sl->capacity = 0;
}

2.尾插函数(在尾部插入数据)

        写尾插函数之前我们得先判断一下数组空间是否够。例如下面的例子。

所以我们要先检查空间是否满了,满了就扩容

C语言动态顺序表实例代码

将这个判断空间函数命名为  void CheckSpace(SL* sl) (这是动态顺序表区别于静态顺序表最主要的部分) 

void CheckSpace(SL* sl)
{
	if (sl->size == sl->capacity)
	{
		//因为capacity一开始等于0,所以先给capacity一个值
		int newcapacity = sl->capacity == 0 ? 4 : sl->capacity * 2;
		DataType* tmp = (DataType*)realloc(sl->a, sizeof(DataType)*newcapacity);
		if (tmp == NULL)
		{
			printf("开辟失败\n");
			exit(-1);
		}
		else
		{
			sl->capacity = newcapacity;
			sl->a = tmp;
		}
	}
}

尾插函数:

void SeqListPushBack(SL* sl, DataType x)
{
CheckSpace(sl);
	sl->a[sl->size] = x;
	sl->size++;
}

3.头插函数(在数组头部插入数据)

        C语言动态顺序表实例代码

void SeqListPushFront(SL* sl, DataType x)
{
	//因为插入的时候都要检查空间是不是满了,满了就扩容
	CheckSpace(sl);
	for (int end = sl->size - 1; end >= 0; end--)
	{
		sl->a[end + 1] = sl->a[end];
	}
	sl->a[0] = x;
	sl->size++;
}

 挪数据对应着for循环的代码,最后再给数组的第一个位置赋值。别忘了对size+1.

 4.尾删函数

        如果size等于0了就说明顺序表中没有数据了,所以

void SeqListPopBack(SL* sl)
{
	assert(sl->size > 0);
	sl->size--;
}

5.头删函数

        从第二个数据开始整体往前挪以为就可以了。(要从前面开始挪):

C语言动态顺序表实例代码

void SeqListPopFront(SL* sl)
{
	for (int i = 1; i < sl->size; i++)
	{
		sl->a[i - 1] = sl->a[i];
	}
	sl->size--;
}

6.在第pos的位置插入数据

        首先pos不能小于现有的数据个数。

        第二判断空间,满了就扩容。

        第三:从第pos个位置的数据开始(这里第pos个位置的数据在数组中的下标是pos-1) 将后面的数据整体往后挪一位。

C语言动态顺序表实例代码

        第四:再这个位置赋值,别忘了对size++;

void SeqListInsert(SL* sl, int pos, DataType x)
{
	//查看空间
	assert(pos <= sl->size);
	CheckSpace(sl);
	for (int end = sl->size-1; end >= pos-1; end--)//这里不能用sl->size--
	{
		sl->a[end+1] = sl->a[end];
	}
	sl->a[pos - 1] = x;
	sl->size++;
}

7.删除第pos个位置的数据

        首先pos不能小于现有数据个数

        第二:将从第pos个位置的数据开始到最后一个数据往前挪一位

C语言动态顺序表实例代码

        第三:对size-- 

void SeqListErase(SL* sl, int pos)
{
	assert(pos <=sl->size);
	for (int i = pos; i < sl->size; i++)
	{
		sl->a[i - 1] = sl->a[i];
	}
	sl->size--;
}

8.修改第pos个位置的数据

        一:pos不能小于现有数据个数

        二:赋值。第pos个位置的数据在数组中下标是pos-1。(因为数组下表从0开始)

void SeqListModify(SL* sl, int pos, DataType x)
{
	assert(pos <= sl->size);
	sl->a[pos - 1] = x;
}

9.查找函数。

        遍历一遍看是否有这个数据,有就返回数据是第几个元素。(这里我不是返回该数据在数组中的下标,我是返回 下标+1) 

        这里我没有考虑如果有两个一样的数据的情况。

int SeqListFind(SL* sl, DataType x)
{
	for (int i = 0; i < sl->size;i++)
	{
		if (sl->a[i] == x)
		{
			i++;
			printf("在第%d个位置\n", i);
			return i;
		}
	}
	printf("没有此数据\n");
	return -1;
}

10.销毁函数

        释放sl->a之后要对它置空,因为指针free之后,free函数只是把指针指向的内存空间释放了,即内存中存储的值,但是并没有将指针的值赋为NULL,指针仍然指向这块内存。 

void SeqListDestory(SL* sl)
{
	free(sl->a);
	sl->a = NULL;
	sl->size = 0;
	sl->capacity = 0;
}

11.打印函数

void SeqListPrint(SL* sl)
{
	for (int i = 0; i < sl->size;i++)
	{
		printf("%d ", sl->a[i]);
	}
	printf("\n");
}

 

三、总代码:

        菜单写的比较简单。

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<assert.h>

typedef int DataType;
typedef struct SeqList
{
	DataType* a;
	int size;
	int capacity;
}SL;

void SeqListInit(SL* sl)
{
	sl->a = NULL;
	sl->size = 0;
	sl->capacity = 0;
}

void SeqListPrint(SL* sl)
{
	for (int i = 0; i < sl->size; i++)
	{
		printf("%d ", sl->a[i]);
	}
	printf("\n");
}

void CheckSpace(SL* sl)
{
	if (sl->size == sl->capacity)
	{
		//因为capacity一开始等于0,所以先给capacity一个值
		int newcapacity = sl->capacity == 0 ? 4 : sl->capacity * 2;
		DataType* tmp = (DataType*)realloc(sl->a, sizeof(DataType)*newcapacity);
		if (tmp == NULL)
		{
			printf("开辟失败\n");
			exit(-1);
		}
		else
		{
			sl->capacity = newcapacity;
			sl->a = tmp;
		}
	}
}

void SeqListPushBack(SL* sl, DataType x)
{
	//看空间是不是满了,满了就扩容
	//if (sl->size == sl->capacity)
	//{
	//	//因为capacity一开始等于0,所以先给capacity一个值
	//	int newcapacity = sl->capacity == 0 ? 4 : sl->capacity * 2;
	//	DataType* tmp = (DataType*)realloc(sl->a, sizeof(DataType)*newcapacity);
	//	if (tmp == NULL)
	//	{
	//		printf("开辟失败\n");
	//		exit(-1);
	//	}
	//	else
	//	{
	//		sl->a = tmp;
	//	}
	//}
	//封装成一个函数
	CheckSpace(sl);
	sl->a[sl->size] = x;
	sl->size++;
}

void SeqListPushFront(SL* sl, DataType x)
{
	//因为插入的时候都要检查空间是不是满了,满了就扩容
	CheckSpace(sl);
	for (int end = sl->size - 1; end >= 0; end--)
	{
		sl->a[end + 1] = sl->a[end];
	}
	sl->a[0] = x;
	sl->size++;
}

void SeqListPopBack(SL* sl)
{
	assert(sl->size > 0);
	sl->size--;
}

void SeqListPopFront(SL* sl)
{
	for (int i = 1; i < sl->size; i++)
	{
		sl->a[i - 1] = sl->a[i];
	}
	sl->size--;
}

void SeqListInsert(SL* sl, int pos, DataType x)
{
	//查看空间
	assert(pos <= sl->size);
	CheckSpace(sl);
	for (int end = sl->size - 1; end >= pos - 1; end--)//这里不能用sl->size--
	{
		sl->a[end + 1] = sl->a[end];
	}
	sl->a[pos - 1] = x;
	sl->size++;
}

void SeqListErase(SL* sl, int pos)
{
	assert(pos <= sl->size);
	for (int i = pos; i < sl->size; i++)
	{
		sl->a[i - 1] = sl->a[i];
	}
	sl->size--;
}

void SeqListModify(SL* sl, int pos, DataType x)
{
	assert(pos <= sl->size);
	sl->a[pos - 1] = x;
}

int SeqListFind(SL* sl, DataType x)
{
	for (int i = 0; i < sl->size; i++)
	{
		if (sl->a[i] == x)
		{
			i++;
			printf("在第%d个位置\n", i);
			return i;
		}
	}
	printf("没有此数据\n");
	return -1;
}

void SeqListDestory(SL* sl)
{
	free(sl->a);
	sl->a = NULL;
	sl->size = 0;
	sl->capacity = 0;
}


void menu()
{
	printf("******************************\n");
	printf("*** 1.尾插数据  2.头插数据 ***\n");
	printf("*** 3.在第pos个位置插入数据***\n");
	printf("*** 4.尾删数据  5.头删数据 ***\n");
	printf("*** 6.在第pos个位置删除数据***\n");
	printf("*** 7.修改第pos个位置的数据***\n");
	printf("*** 8.查找数据 9.打印数据  ***\n");
	printf("********** -1.退出 ***********\n");
	printf("******************************\n");
}
int main()
{
	SL sl;
	SeqListInit(&sl);
	int option = 0;
	int x = 0;
	int pos = 1;
	while (option != -1)
	{
		menu();
		scanf("%d", &option);
		switch (option)
		{
		case 1:
			printf("请输入要插入的数据,以-1结束:\n");
			do
			{
				scanf("%d", &x);
				if (x != -1)
				{
					SeqListPushBack(&sl, x);
				}
			} while (x != -1);
			break;
		case 2:
			printf("请输入要插入的数据,以-1结束:\n");
			do
			{
				scanf("%d", &x);
				if (x != -1)
				{
					SeqListPushFront(&sl, x);
				}
			} while (x != -1);
			break;
		case 3:
			printf("请输入要插入的数据,要从第几个插入,以非正正数结束\n");
			do
			{
				scanf("%d", &x);
				scanf("%d", &pos);
				if (pos >= 0)
				{
					SeqListInsert(&sl, pos, x);
				}
			} while (pos >= 0);
			break;
		case 4:
			SeqListPopBack(&sl);
			break;
		case 5:
			SeqListPopFront(&sl);
			break;
		case 6:
			printf("请输入要删除第几个位置的数据,以非正正数结束\n");
			do
			{
				scanf("%d", &pos);
				if (pos>0)
				{
					SeqListErase(&sl, pos);
				}
			} while (pos>0);
			break;
		case 7:
			printf("请输入要修改的数据,要修改第几个数据,以非正整数结束\n");
			do
			{
				scanf("%d", &x);
				scanf("%d", &pos);
				if (pos>0)
				{
					SeqListInsert(&sl, pos, x);
				}
			} while (pos>0);
			break;
		case 8:
			printf("请输入需要查找的数据\n");
			scanf("%d", &x);
			SeqListFind(&sl, x);
			break;
		case 9:
			SeqListPrint(&sl);
			break;
		case -1:
			printf("退出\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
		}
	}
	SeqListDestory(&sl);
	return 0;
}

到此这篇关于C语言动态顺序表实例代码的文章就介绍到这了,更多相关C语言顺序表内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/weixin_53936115/article/details/122013467

延伸 · 阅读

精彩推荐
  • C/C++详解C++中OpenSSL动态链接库的使用

    详解C++中OpenSSL动态链接库的使用

    这篇文章主要介绍了OpenSSL动态链接库的使用,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参...

    尘世中迷途小码农4382022-02-23
  • C/C++学习二维动态数组指针做矩阵运算的方法

    学习二维动态数组指针做矩阵运算的方法

    这片文章介绍了如何利用二维动态数组指针做矩阵运算,需要的朋友可以参考下...

    王维来5922021-03-04
  • C/C++C++输入输出注意事项总结

    C++输入输出注意事项总结

    这篇文章主要介绍了C++输入输出注意事项总结,对C++的输入输出各个注意事项进行了很好的总结,需要的朋友可以参考下...

    C++教程网5742021-01-29
  • C/C++基于linux下获取时间函数的详解

    基于linux下获取时间函数的详解

    本篇文章是对linux下获取时间的函数进行了详细的分析介绍,需要的朋友参考下...

    C语言教程网3222020-12-08
  • C/C++使用C++调用Python代码的方法步骤

    使用C++调用Python代码的方法步骤

    这篇文章主要介绍了使用C++调用Python代码的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们...

    风向晚。9102021-08-13
  • C/C++MFC实现字幕滚动效果

    MFC实现字幕滚动效果

    这篇文章主要为大家详细介绍了MFC实现滚动字幕,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    一枪尽骚丶魂8952021-09-09
  • C/C++C++实现LeetCode(110.平衡二叉树)

    C++实现LeetCode(110.平衡二叉树)

    这篇文章主要介绍了C++实现LeetCode(110.平衡二叉树),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下...

    Grandyang8102021-12-02
  • C/C++C语言编程数据结构基础详解小白篇

    C语言编程数据结构基础详解小白篇

    这篇文章主要介绍了数据结构的基础,非常适合初学数据结构的小白,有需要的朋友可以借鉴参考下,希望可以有所帮助,祝大家多多进步,早日升职加薪...

    Booksort8982022-01-07