顺序表的本质是数组,它们在内存上是连续存储的。而链表则是由散落的点,通过地址连接起来的链。链表的一个节点分为值域和指针域,值域用于存储当前节点的数值,以单链表为例,指针域存储的是其下一个节点的地址,链表正是以这种方法链接起来的。
而顺序表则是一个数组,只不过它会实时记录自己的长度,当长度不够的时候会自动扩容。值得注意的是扩容会有不少的消耗,因此我们每次都会扩容两倍或1.5倍。顺序表的好处是一个动态的数组更方便我们进行广泛的编程,适用性更强,且不会造成过多的空间浪费。
顺序表和链表是两种常见的数据结构,用于存储和管理数据集合。以下是它们的基本概念和主要区别:
顺序表:
链表:
总结:
接下来我将把顺序表和链表的相关代码贴上去:
顺序表:
头文件:
#pragma once
#include
#include
#include
typedef int SLDateType;
typedef struct SeqList
{
SLDateType* a;
int size;
int capacity;
}SeqList;
// 对数据的管理:增删查改
void SeqListInit(SeqList* ps);
void SeqListDestroy(SeqList* ps);
void SeqListPrint(SeqList* ps);
void SeqListPushFront(SeqList* ps, SLDateType x);
void SeqListPushBack(SeqList* ps, SLDateType x);
void SeqListPopFront(SeqList* ps);
void SeqListPopBack(SeqList* ps);
// 顺序表查找
int SeqListFind(SeqList* ps, SLDateType x);
// 顺序表在pos位置插入x
void SeqListInsert(SeqList* ps, int pos, SLDateType x);
// 顺序表删除pos位置的值
void SeqListErase(SeqList* ps, int pos);
函数实现:
#include "SeqList.h"
void SeqListInit(SeqList* ps)
{
assert(ps);
ps->a = NULL;
ps->size = 0;
ps->capacity = 0;
}
void SeqListDestroy(SeqList* ps)
{
assert(ps);
if (ps->a != NULL)
{
free(ps->a);
ps->a = NULL;
ps->size = 0;
ps->capacity = 0;
}
}
void SeqListPrint(SeqList* ps)
{
assert(ps);
int i = 0;
for (i = 0; i < ps->size; ++i)
{
printf("%d ", ps->a[i]);
}
printf("\n");
}
static void SLCheckCapacity(SeqList* ps)
{
assert(ps);
if (ps->size == ps->capacity)
{
int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
SLDateType* tmp = (SLDateType*)realloc(ps->a, sizeof(SLDateType) * newcapacity);
if (tmp == NULL)
{
perror("realloc fail");
return;
}
ps->a = tmp;
ps->capacity = newcapacity;
}
}
void SeqListPushFront(SeqList* ps, SLDateType x)
{
assert(ps);
SLCheckCapacity(ps);
int i = 0;
for (i = ps->size; i >= 0; --i)
{
ps->a[i] = ps->a[i - 1];
}
ps->a[0] = x;
ps->size++;
}
void SeqListPushBack(SeqList* ps, SLDateType x)
{
assert(ps);
SLCheckCapacity(ps);
ps->a[ps->size] = x;
ps->size++;
}
void SeqListPopFront(SeqList* ps)
{
assert(ps);
if (ps->size)
{
int i = 0;
for (i = 0; i < ps->size - 1; ++i)
{
ps->a[i] = ps->a[i + 1];
}
ps->size--;
}
return;
}
void SeqListPopBack(SeqList* ps)
{
assert(ps);
if (ps->size)
{
ps->a[ps->size - 1] = 0;
ps->size--;
}
return;
}
int SeqListFind(SeqList* ps, SLDateType x)
{
assert(ps);
int i = 0;
for (i = 0; i < ps->size; ++i)
{
if (ps->a[i] == x)
return i;
}
return -1;
}
void SeqListInsert(SeqList* ps, int pos, SLDateType x)
{
assert(ps);
if ((pos >= 0 && pos < ps->size))
{
SLCheckCapacity(ps);
int i = 0;
for (i = ps->size; i >= pos; --i)
{
ps->a[i] = ps->a[i - 1];
}
ps->a[pos] = x;
ps->size++;
}
return;
}
void SeqListErase(SeqList* ps, int pos)
{
assert(ps);
if (ps->size && (pos>=0 && pos < ps->size))
{
int i = 0;
for (i = pos; i < ps->size - 1; ++i)
{
ps->a[i] = ps->a[i + 1];
}
ps->size--;
ps->a[ps->size] = 0;
}
return;
}
链表
头文件:
#pragma once
#include
#include
#include
typedef int SLTDateType;
typedef struct SListNode
{
SLTDateType data;
struct SListNode* next;
}SListNode;
// 动态申请一个节点
SListNode* BuySListNode(SLTDateType x);
// 单链表打印
void SListPrint(SListNode* plist);
// 单链表尾插
void SListPushBack(SListNode** pplist, SLTDateType x);
// 单链表的头插
void SListPushFront(SListNode** pplist, SLTDateType x);
// 单链表的尾删
void SListPopBack(SListNode** pplist);
// 单链表头删
void SListPopFront(SListNode** pplist);
// 单链表查找
SListNode* SListFind(SListNode* plist, SLTDateType x);
// 单链表在pos位置之后插入x
// 分析思考为什么不在pos位置之前插入?
void SListInsertAfter(SListNode** pplist, SListNode** pos, SLTDateType x);
// 单链表删除pos位置之后的值
// 分析思考为什么不删除pos位置?
void SListEraseAfter(SListNode** pplist, SListNode** ppos);
// 在pos的前面插入
void SLTInsert(SListNode** pphead, SListNode** ppos, SLTDateType x);
// 删除pos位置
void SLTErase(SListNode** pplist, SListNode** ppos);
void SLTDestroy(SListNode** pplist);
函数的实现:
#include "SList.h"
// 动态申请一个节点
SListNode* BuySListNode(SLTDateType x)
{
SListNode* ret = (SListNode*)malloc(sizeof(SListNode));
if (ret == NULL)
{
perror("malloc");
exit(0);
}
ret->data = x;
ret->next = NULL;
return ret;
}
// 单链表打印
void SListPrint(SListNode* plist)
{
if (plist == NULL)
{
printf("NULL\n");
return;
}
SListNode* tmp = plist;
while (tmp)
{
printf("%d->", tmp->data);
tmp = tmp->next;
}
printf("NULL\n");
}
// 单链表尾插
void SListPushBack(SListNode** pplist, SLTDateType x)
{
assert(pplist);
SListNode* NewNode = BuySListNode(x);
if (*pplist == NULL)
{
*pplist = NewNode;
}
else
{
//找尾
SListNode* tmp = *pplist;
while (tmp->next)
{
tmp = tmp->next;
}
tmp->next = NewNode;
}
}
// 单链表的头插
void SListPushFront(SListNode** pplist, SLTDateType x)
{
assert(pplist);
SListNode* NewNode = BuySListNode(x);
SListNode* tmp = *pplist;
*pplist = NewNode;
NewNode->next = tmp;
}
// 单链表的尾删
void SListPopBack(SListNode** pplist)
{
assert(pplist);
if (*pplist == NULL)
return;
SListNode* tmp = *pplist;
SListNode* prev = NULL;
if (tmp->next == NULL)
{
*pplist = NULL;
free(tmp);
return;
}
//找尾
while (tmp->next)
{
prev = tmp;
tmp = tmp->next;
}
free(tmp);
(prev->next) = NULL;
}
// 单链表头删
void SListPopFront(SListNode** pplist)
{
assert(pplist);
if (*pplist == NULL)
return;
SListNode* old_head = *pplist;
*pplist = (*pplist)->next;
free(old_head);
}
// 单链表查找
SListNode* SListFind(SListNode* plist, SLTDateType x)
{
if (plist == NULL)
return NULL;
SListNode* tmp = plist;
while (tmp != NULL)
{
if (tmp->data == x)
return tmp;
tmp = tmp->next;
}
return NULL;
}
//销毁链表
void SLTDestroy(SListNode** pplist)
{
assert(pplist);
if (*pplist == NULL)
return;
int count = 1;
SListNode* tmp = *pplist;
while (tmp->next)
{
tmp = tmp->next;
count++;
}
while (count--)
{
SListPopBack(pplist);
}
}
// 单链表在pos位置之后插入x
void SListInsertAfter(SListNode** pplist, SListNode** ppos, SLTDateType x)
{
SListNode* NewNode = BuySListNode(x);
if ((*ppos == NULL) && (*pplist = NULL))
{
SListPushFront(pplist, x);
return;
}
SListNode* tmp = *pplist;
SListNode* after = *pplist;
while ((tmp->next) != NULL)
{
after = tmp->next;
if (tmp == *ppos)
{
((*ppos)->next) = NewNode;
NewNode->next = after;
return;
}
tmp = tmp->next;
}
if (*ppos == tmp)
{
tmp->next = NewNode;
return;
}
perror("The pointer does not exist");
}
// 单链表删除pos位置之后的值
void SListEraseAfter(SListNode** pplist, SListNode** ppos)
{
if ((*ppos == NULL) && (*pplist = NULL))
return;
else if ((*ppos)->next == NULL)
return;
SListNode* tmp = *pplist;
SListNode* after = *pplist;
SListNode* aafter = *pplist;
while ((tmp->next) != NULL)
{
after = tmp->next;
aafter = after->next;
if (tmp == *ppos)
{
free(after);
after = NULL;
tmp->next = aafter;
return;
}
tmp = tmp->next;
}
if (*ppos == tmp)
return;
else
perror("The pointer does not exist");
}
// 在pos的前面插入
void SLTInsert(SListNode** pplist, SListNode** ppos, SLTDateType x)
{
assert(pplist);
if (*pplist == *ppos)
{
SListPushFront(pplist, x);
return;
}
SListNode* NewNode = BuySListNode(x);
SListNode* tmp = *pplist;
SListNode* prev = *pplist;
while (tmp->next)
{
if (tmp == *ppos)
{
prev->next = NewNode;
NewNode->next = tmp;
return;
}
prev = tmp;
tmp = tmp->next;
}
perror("The pointer does not exist");
}
// 删除pos位置
void SLTErase(SListNode** pplist, SListNode** ppos)
{
if ((*ppos == NULL) || (*pplist == NULL))
{
return;
}
else if ((*ppos)->next == NULL)
{
SListPopBack(pplist);
return;
}
SListNode* tmp = *pplist;
SListNode* befor = *pplist;
SListNode* after = *pplist;
while ((tmp->next) != NULL)
{
after = tmp->next;
if (tmp == *ppos)
{
free(tmp);
tmp = NULL;
befor->next = after;
return;
}
befor = tmp;
tmp = tmp->next;
}
if (*ppos == tmp)
return;
else
perror("The pointer does not exist");
}