顺序表的缺点
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;
}