线性表之单链表

顺序表的缺点

1、空间不够了需要增容,增容是要付出代价的
2、避免频繁扩容,我们满了基本都是扩2倍可能就会导致一定的空间浪费
3、顺序表要求数据从开始位置连续存储那么我们在头部或者中间位置插入删除数据就需要挪动数据,效率不高
针对顺序表的缺点于是有了链表

链表的实现

SList.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>



typedef int SLTdatetype;

typedef struct SList
{
	SLTdatetype data;
	struct SList* next;
}SLNODE;



//打印
void SListPrint(SLNODE* phead);
//尾插
void SListPushBack(SLNODE** pphead, SLTdatetype x);
//头插
void SListPushFront(SLNODE** pphead, SLTdatetype x);
//头删
void SListPopFront(SLNODE** pphead);
//尾删
void SListPopBack(SLNODE** pphead);
//查找,返回元素地址兼修改
SLNODE* SListFind(SLNODE* head, SLTdatetype x);
//在pos位置之前去插入一个节点
void SListInsertBefore(SLNODE** pphead, SLNODE* pos,SLTdatetype x);
//在pos位置之后去插入一个节点
void SListInsertAfter(SLNODE** pphead, SLNODE* pos, SLTdatetype x);
//删除pos位置的数据
void SListEase(SLNODE** pphead,SLNODE* pos);
//销毁
void SListDestory(SLNODE** pphead);
SList.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"SList.h"

//打印
void SListPrint(SLNODE* phead)
{
	SLNODE* cur = phead;
	while (cur != NULL)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("\n");
}


//尾插
void SListPushBack(SLNODE** pphead, SLTdatetype x)
{
	//开辟新空间并且将地址给尾指针
	SLNODE* newnode = (SLNODE*)malloc(sizeof(SLNODE));
	newnode->data = x;
	newnode->next = NULL;
	
	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	else
	{
		struct SList* tail = *pphead;
		//找到尾指针
		while (tail->next != NULL)
		{
			tail=tail->next;
		}
		tail->next = newnode;
	}
}
//头插
void SListPushFront(SLNODE** pphead, SLTdatetype x)
{
	SLNODE* newnode = (SLNODE*)malloc(sizeof(SLNODE));
	if (newnode == NULL)
		perror("malloc fail");
	//将新开辟节点指向原来的头
	newnode->next = *pphead;
	newnode->data = x;
	//使头节点成为最前面的那个
	*pphead = newnode;
}
//头删
void SListPopFront(SLNODE** pphead)
{
	assert(*pphead != NULL);
	SLNODE* head = *pphead;
	*pphead = head->next;
	//释放原来的头
	free(head);
}
//尾删
void SListPopBack(SLNODE** pphead)
{
	assert(*pphead != NULL);
	//情况一只有一个节点
	if ((*pphead)->next == NULL)
	{
		(*pphead)->data = 0;
		free(*pphead);
		*pphead = NULL;
	}//情况二有两个及以上的节点
	else
	{
		//方法一(双指针)
		
		//SLNODE* tail = *pphead;
		//SLNODE* prve = NULL;
		//while (tail->next != NULL)
		//{
		//	prve = tail;
		//	tail = tail->next;
		//}
		//free(tail);
		//prve->next = NULL;
	

		//方法二
		SLNODE* tail = *pphead;
		while (tail->next->next)
		{
			tail = tail->next;
		}
		free(tail->next);
		tail->next = NULL;
	}
}


//查找,返回元素地址兼修改
SLNODE* SListFind(SLNODE* head, SLTdatetype x)
{
	SLNODE* cur = head;
	while (cur->next)
	{
		if (cur->data == x)
		{
			return cur;
		}
		else
		{
			cur = cur->next;
		}
	}
}
//在pos位置之前去插入一个节点
void SListInsertBefore(SLNODE** pphead,SLNODE* pos,SLTdatetype x)
{
	if (*pphead == pos)
	{
		//此时效果相当于头插
		SListPushFront(pphead, x);
	}
	else
	{
		SLNODE* posprev = *pphead;
		while (posprev->next != pos)
		{
			posprev = posprev->next;
		}
		SLNODE* newnode = (SLNODE*)malloc(sizeof(SLNODE));
		newnode->data = x;
		//连接pos节点
		newnode->next = pos;
		//连接pos前面的节点
		posprev->next = newnode;
	}
}

//在pos位置之后去插入一个节点
void SListInsertAfter(SLNODE** pphead, SLNODE* pos, SLTdatetype x)
{
	if (*pphead == pos)
	{
		//此时效果相当于尾插
		SListPushBack(pphead, x);
	}
	else
	{
		SLNODE* posbck = *pphead;
		while (posbck!= pos)
		{
			posbck = posbck->next;
		}
		//让posbck到pos后面那里
		posbck = posbck->next;
		SLNODE* newnode = (SLNODE*)malloc(sizeof(SLNODE));
		newnode->data = x;
		//连接pos后面的节点
		newnode->next = posbck;
		//连接pos
		pos->next = newnode;
	}
}

void SListEase(SLNODE** pphead,SLNODE* pos)
{
	SLNODE* pre = *pphead;
	while (pre->next != pos)
	{
		pre = pre->next;
	}
	pre->next = pos->next;
	free(pos);
	pos = NULL;
}

void SListDestory(SLNODE** pphead)
{
	while (*pphead != NULL)
	{
		SLNODE* back = *pphead;
		free(*pphead);
		*pphead = back;
	}
	printf("exit delete");
}

test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"SList.h"
#include<Windows.h>


void test1()
{
	SLNODE* x=NULL;

	SListPushBack(&x, 1);
	SListPushBack(&x, 2);
	SListPushBack(&x, 3);
	SLNODE* pos=SListFind(x, 2);
	SListInsertAfter(&x,pos,4);
	SListInsertBefore(&x, pos, 0);
	SListEase(&x, pos);
	SListPrint(x);
}


int main()
{
	test1();
	return 0;
}
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值