单链表的实现

单链表的定义

        由于顺序表的插入删除操作需要移动大量的元素,影响了运行效率,因此引入了线性表的链式存储——单链表。单链表通过一组任意的存储单元来存储线性表中的数据元素,因此它不要求在逻辑上相邻的两个元素在物理位置上也相邻。

单链表的实现

初始化

我们要先定义一个单链表的结构体,单链表需要一个链表的指针,链表中数据的个数,链表的空间大小,

typedef int SQDatatype;
typedef struct SeqList
{
	SQDatatype* ps;
	int size;
	int capacity;
}SL;

 初始化链表时链表指针指向空,链表内元素个数为0,链表空间为0;

//初始化
void SLInit(SL* s1)
{
	assert(s1);
	s1->ps = NULL;
	s1->size = 0;//链表内数据个数
	s1->capacity = 0;//链表空间
}

 检查扩容

        每次插入数据时我们都要检查一下链表的空间是否足够,因此可以专门下一个检查扩容的函数;

void SLCheckCapacity(SL* s1)
{
	assert(s1);
	//链表内个数和链表空间相等时需要扩容
	if (s1->size == s1->capacity)
	{
		int newcapacity = s1->capacity == 0 ? 4 : s1->capacity * 2;
		SQDatatype* tem = (SQDatatype*)realloc(s1->ps, newcapacity * sizeof(SQDatatype));
		if (tem == NULL)
		{
			perror("realloc fail");
			return;
		}
		s1->ps = tem;
		s1->capacity = newcapacity;
	}
}

        注意扩容时要用realloc而不是malloc,malloc是重新开辟空间,会覆盖之前的数据,(因为我之前写的时候,就写错成了malloc,检查了老半天);

头插

//头插
void SLPushFront(SL* s1, SQDatatype x)
{
	assert(s1);
	SLCheckCapacity(s1);
	for (int i = s1->size; i > 0; i--)
	{
		s1->ps[i] = s1->ps[i - 1];
	}
	s1->ps[0] = x;
	s1->size++;
}

        头插时把原来的元素一个个往后移,然后头插入新的元素,记得s1->size++ ,注意细节;

尾插

//尾插
void SLPushBack(SL* s1, SQDatatype x)
{
	assert(s1);
	SLCheckCapacity(s1);
	s1->ps[s1->size] = x;
	s1->size++;
}

头删

        删除数据时链表不能为空;

//头删
void SLPopFront(SL* s1)
{
	assert(s1);
	assert(s1->size != 0);
	for (int i = 0; i < s1->size - 1; i++)
	{
		s1->ps[i] = s1->ps[i + 1];
	}
	s1->size--;
}

尾删

        删除数据时链表不能为空;

//尾删
void SLPopBack(SL* s1)
{
	assert(s1);
	assert(s1->size != 0);
	s1->size--;
}

指定位置插入

        注意判断pos的值,如果pos不在0到size中,会直接报错,所以要加个断言

//指定位置插入
void SLInsert(SL* s1, int pos, SQDatatype x)
{
	assert(s1);
	assert(pos >= 0 && pos <= s1->size);
	SLCheckCapacity(s1);
	for (int i = s1->size; i > pos; i--)
	{
		s1->ps[i] = s1->ps[i - 1];
	}
	s1->ps[pos] = x;
	s1->size++;

}

指定位置删除

        注意判断pos的值,如果pos不在0到size中,会直接报错,所以要加个断言

//指定位置删除
void SLErase(SL* s1, int pos)
{
	assert(s1);
	assert(pos >= 0 && pos <= s1->size);
	for (int i = pos; i < s1->size - 1; i++)
	{
		s1->ps[i] = s1->ps[i + 1];
	}
	s1->size--;
}

总结(废话)

        单链表是动态的顺序表,对于初学者可以锻炼自己的代码能力,当你熟悉之后就会发现很简单,难点就是初学时不清楚细节,还是要多多练习; 

        一起加油!

完整代码

#pragma once

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

typedef int SQDatatype;
typedef struct SeqList
{
	SQDatatype* ps;
	int size;
	int capacity;
}SL;
//初始化
void SLInit(SL* s1);
//检查扩容
void SLCheckCapacity(SL* s1);
//头插
void SLPushFront(SL* s1, SQDatatype x);
//尾插
void SLPushBack(SL* s1, SQDatatype x);
//头删
void SLPopFront(SL* s1);
//尾删
void SLPopBack(SL* s1);
//指定位置插入
void SLInsert(SL* s1, int pos, SQDatatype x);
//指定位置删除
void SLErase(SL* s1, int pos);
//查找数据
void SLFind(SL* s1, SQDatatype x);
//修改数据
void SLModity(SL* s1, int pos, SQDatatype x);
//打印链表
void SLPrintf(SL* s1);
//销毁链表
void SLDestroy(SL* s1);
#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"

void SLInit(SL* s1)
{
	assert(s1);
	s1->ps = NULL;
	s1->size = 0;//链表内数据个数
	s1->capacity = 0;//链表空间
}

void SLCheckCapacity(SL* s1)
{
	assert(s1);
	//链表内个数和链表空间相等时需要扩容
	if (s1->size == s1->capacity)
	{
		int newcapacity = s1->capacity == 0 ? 4 : s1->capacity * 2;
		SQDatatype* tem = (SQDatatype*)realloc(s1->ps, newcapacity * sizeof(SQDatatype));
		if (tem == NULL)
		{
			perror("realloc fail");
			return;
		}
		s1->ps = tem;
		s1->capacity = newcapacity;
	}
}
//头插
void SLPushFront(SL* s1, SQDatatype x)
{
	assert(s1);
	SLCheckCapacity(s1);
	for (int i = s1->size; i > 0; i--)
	{
		s1->ps[i] = s1->ps[i - 1];
	}
	s1->ps[0] = x;
	s1->size++;
}
//尾插
void SLPushBack(SL* s1, SQDatatype x)
{
	assert(s1);
	SLCheckCapacity(s1);
	s1->ps[s1->size] = x;
	s1->size++;
}

//头删
void SLPopFront(SL* s1)
{
	assert(s1);
	assert(s1->size != 0);
	for (int i = 0; i < s1->size - 1; i++)
	{
		s1->ps[i] = s1->ps[i + 1];
	}
	s1->size--;
}
//尾删
void SLPopBack(SL* s1)
{
	assert(s1);
	assert(s1->size != 0);
	s1->size--;
}
//指定位置插入
void SLInsert(SL* s1, int pos, SQDatatype x)
{
	assert(s1);
	assert(pos >= 0 && pos <= s1->size);
	SLCheckCapacity(s1);
	for (int i = s1->size; i > pos; i--)
	{
		s1->ps[i] = s1->ps[i - 1];
	}
	s1->ps[pos] = x;
	s1->size++;

}
//指定位置删除
void SLErase(SL* s1, int pos)
{
	assert(s1);
	assert(pos >= 0 && pos <= s1->size);
	for (int i = pos; i < s1->size - 1; i++)
	{
		s1->ps[i] = s1->ps[i + 1];
	}
	s1->size--;
}
//查找数据
void SLFind(SL* s1, SQDatatype x)
{
	assert(s1);
	int flag = 0;
	for (int i = 0; i < s1->size; i++)
	{
		if (s1->ps[i] == x)
		{
			flag = 1;
			printf("找到了,在下表为%d的位置\n", i);

		}
	}
	if(flag==0)
	printf("该数据不存在\n");
}

//修改数据
void SLModity(SL* s1, int pos, SQDatatype x)
{
	assert(s1);
	assert(pos >= 0 && pos <= s1->size);
	s1->ps[pos] = x;
}
//打印链表
void SLPrintf(SL* s1)
{
	assert(s1);
	for (int i = 0; i < s1->size; i++)
	{
		printf("%d ", s1->ps[i]);
	}
	printf("\n");
}
//销毁链表
void SLDestroy(SL* s1)
{
	assert(s1);
	free(s1->ps);
	SLInit(s1);
}

#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"
int main()
{
	SL s1;
	SLInit(&s1);
	SLPushFront(&s1, 1);
	SLPushFront(&s1, 2);
	SLPushFront(&s1, 3);
	SLPushFront(&s1, 4);
	SLPushFront(&s1, 5);
	SLPushBack(&s1, 100);
	SLPushBack(&s1, 200);
	SLPushBack(&s1, 300);
	SLPushBack(&s1, 400);
	SLPushBack(&s1, 500);
	/*SLPopBack(&s1);
	SLPopBack(&s1);
	SLPopBack(&s1);
	SLPopBack(&s1);*/
	/*SLErase(&s1, 2);*/
	SLModity(&s1, 3, 5000);
	SLFind(&s1, 5000);
	SLPrintf(&s1);
	SLDestroy(&s1);
	return 0;
}

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值