数据结构顺序表——链表

Posted Huang_ZhenSheng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构顺序表——链表相关的知识,希望对你有一定的参考价值。

目录

顺序表

头文件SeqList.h:

测试文件8.6.c:

文件运行SeqList.c:

小结:

下面继续接着实现3个接口:

查找:

在中间插入某个数(重要!):

删除某个数:

菜单:

完整代码:顺序表


顺序表

可动态增长的数组,要求数据是连续存储的

(类似通讯录,本文直接上代码哦)

头文件SeqList.h:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SQDataType;

typedef struct SeqList
{
	SQDataType* a;
	int size;//有效数据的个数
	int capacity;//容量空间的大小
}SLT;

//增删查改
void SeqListInit(SLT* ps1);//初始化
void SeqListDestory(SLT* ps1);
void SeqListPushBack(SLT* ps1, SQDataType x);
void SeqListPushfront(SLT* ps1, SQDataType x);
void SeqListPrint(SLT* Ps1);

void SeqListCheckCapacity(SLT* ps1);

//尾插尾删,头插头删
void SeqListPushBack(SLT* ps1, SQDataType x);//时间复杂度O(1)
void SeqListPushFront(SLT* ps1,SQDataType x);//时间复杂度O(N)
void SeqListPopBack(SLT* ps1);//时间复杂度O(1)
void SeqListPopFront(SLT* ps1);//时间复杂度O(N)

测试文件8.6.c:

#include"SeqList.h"
void TestSeqList()
{
	SLT s;
	SeqListInit(&s);
	SeqListCheckCapacity(&s);
	SeqListPushBack(&s, 1);//尾插 
	SeqListPushBack(&s, 2);//尾插 
	SeqListPushBack(&s, 3);//尾插
	SeqListPrint(&s);

	SeqListPushFront(&s, -1);//头插
	SeqListPrint(&s);

	SeqListPopBack(&s);//尾删
	SeqListPrint(&s);

	SeqListPopFront(&s);//头删
	SeqListPrint(&s);

	SeqListPopFront(&s);//头删
	SeqListPrint(&s);

	SeqListPopFront(&s);//头删
	SeqListPrint(&s);


	SeqListDestory(&s);
}
int main()
{
	TestSeqList();
	return 0;
}

文件运行SeqList.c:

#include"SeqList.h"
void SeqListInit(SLT* ps1)
{
	assert(ps1);
	ps1->a = NULL;
	ps1->size = ps1->capacity = 0;
}


void SeqListDestory(SLT* ps1)
{
	assert(ps1);
	if (ps1->a)
	{
		free(ps1->a);
		ps1->a = NULL;
	}
	ps1->size = ps1->capacity = 0;

}

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

//是否满了,满了就要增容
void SeqListCheckCapacity(SLT* ps1)
{
	assert(ps1);
	if (ps1->size == ps1->capacity)
	{
		size_t newcapacity = ps1->capacity == 0 ? 4 : ps1->capacity * 2;
		ps1->a = (SQDataType*)realloc(ps1->a, newcapacity*sizeof(SQDataType));
		ps1->capacity = newcapacity;
	}
}

//尾插尾删,头插头删
void SeqListPushBack(SLT* ps1, SQDataType x)//尾插
{
	assert(ps1);
	SeqListCheckCapacity(ps1);
	ps1->a[ps1->size] = x;
	ps1->size++;
}

void SeqListPushFront(SLT* ps1, SQDataType x)//头插
{
	assert(ps1);
	SeqListCheckCapacity(ps1);
	int end = ps1->size - 1;
	while (end >= 0)
	{
		ps1->a[end + 1] = ps1->a[end];
		end--;
	}
	ps1->a[0] = x;
	ps1->size++;
}

void SeqListPopBack(SLT* ps1)//尾删
{
	assert(ps1);
	assert(ps1->size > 0);
	//ps1->a[ps1->size - 1] = 0;没必要,直接删除
	ps1->size--;
}

void SeqListPopFront(SLT* ps1)//头删
{
	assert(ps1);
	assert(ps1->size > 0);
	int begin = 1;
	while (begin < ps1->size)
	{
		ps1->a[begin - 1] = ps1->a[begin];
		begin++;
	}
	if (ps1->size > 0)
	{
		ps1->size--;
	}
}

小结:

1.空间不够增容

2.插入跟删除都得要求数据要连续

下面继续接着实现3个接口:

查找:

int SeqListFind(SLT* ps1, SQDataType x)//查找
{
	assert(ps1);
	for (int i = 0; i < ps1->size; i++)
	{
		if (ps1->a[i] == x)
		{
			return i;
		}
	}
	return -1;
}

在中间插入某个数(重要!):

注意有符号和无符号

void SeqListInsert(SLT* ps1, size_t  pos, SQDataType x)
{
	assert(ps1);
	assert(pos <= ps1->size && pos>=0);
	SeqListCheckCapacity(ps1);
	//假如pos=0或者end=0,会发生整型提升
	//方案1:将pos强制类型转换成int

	/*int end = ps1->size - 1;
	while (end >= (int)pos)
	{
		ps1->a[end + 1] = ps1->a[end];
		end--;
	}*/


	//方案2(推荐):用size_t要防止这个数变成-1
	size_t end = ps1->size;
	while (end > pos)
	{
		ps1->a[end] = ps1->a[end-1];//防止了end变为-1
		end--;
	}

	ps1->a[pos] = x;
	ps1->size++;
}

总结:要避免负数给到无符号,或者避免有符号数变成负数以后,被提升或者强转成有符号

删除某个数:

void SeqListErase(SLT* ps1, size_t pos)
{
	assert(ps1);
	assert(pos < ps1->size);
	size_t begin = pos;
	while (begin < ps1->size - 1)
	{
		ps1->a[begin] = ps1->a[begin+1];
		begin++;
	}
	ps1->size--;
}

菜单:

void menu()
{
	printf("***********************************\\n");
	printf("       1.尾插数据 2.头插数据       \\n");
	printf("       3.尾删数据 4.头删数据       \\n");
	printf("       5.  打印   0.  退出         \\n");
	printf("***********************************\\n");
}
int main()
{
	int input = 0;
	SLT s;
	SeqListInit(&s);
	int val = 0;
	int front = 0;
	do
	{
		menu();
		printf("请选择操作选项:>");
		scanf("%d", &input);
		switch (input)
		{
		case 0:
			break;
		case 1:
			printf("请输入要尾插数据,以-1结束:");
			scanf("%d",&val);
			while (val != -1)
			{
				SeqListPushBack(&s, val);
				scanf("%d", &val);
			}
			break;
		case 2:
			printf("请输入要头插数据,以-1结束:");
			scanf("%d",&front);
			while (front != -1)
			{
				SeqListPushFront(&s, front);
				scanf("%d",&front);
			}
			break;
		case 3:
			SeqListPopBack(&s);
			break;
		case 4:
			SeqListPopFront(&s);
			break;
		case 5:
			SeqListPrint(&s);
			break;
		default:
			printf("无此选项,请重新输入");
			break;
		}

	}while (input != 0);
	SeqListDestory(&s);
	//TestSeqList();
	//越界不一定报错,系统对越界的检查是一种抽查
	//访问修改数据结构的建议一定用函数去,这样是最安全靠谱的
	return 0;
}

完整代码:顺序表

以上是关于数据结构顺序表——链表的主要内容,如果未能解决你的问题,请参考以下文章

(数据结构)顺序表与链表的基本操作代码以及比较

考研数据结构模板:顺序表链表栈队列

线性表和顺序表的区别

数据结构顺序表——链表

数据结构之线性表代码实现顺序存储,链式存储,静态链表(选自大话数据结构)

数据结构排序算法