SeqList.h
#pragma once
#include
#include
#include
#include
#include
typedef int SLDataType;
// 顺序表的动态存储
typedef struct SeqList
{
SLDataType* array; // 指向动态开辟的数组
size_t size; // 有效数据个数
size_t capicity; // 容量空间的大小
}SeqList;
SeqList SL;
// 基本增删查改接口
// 顺序表初始化
void SeqListInit(SeqList* psl);
// 检查空间,如果满了,进行增容
void CheckCapacity(SeqList* psl);
// 顺序表尾插
void SeqListPushBack(SeqList* psl, SLDataType x);
// 顺序表尾删
void SeqListPopBack(SeqList* psl);
// 顺序表头插
void SeqListPushFront(SeqList* psl, SLDataType x);
// 顺序表头删
void SeqListPopFront(SeqList* psl);
// 顺序表查找
int SeqListFind(SeqList* psl, SLDataType x);
// 顺序表在pos位置插入x
void SeqListInsert(SeqList* psl, size_t pos, SLDataType x);
// 顺序表删除pos位置的值
void SeqListErase(SeqList* psl, size_t pos);
// 顺序表销毁
void SeqListDestory(SeqList* psl);
// 顺序表打印
void SeqListPrint(SeqList* psl);
//顺序表修改
void SLModify(SeqList* psl, size_t pos, SLDataType x);
SeqList.c
#define _CRT_SECURE_NO_WARNINGS
#include "SeqList.h"
// 顺序表初始化
void SeqListInit(SeqList* psl) {
assert(psl);
psl->capicity = 0;
psl->size = 0;
psl->array = NULL;
}
//顺序表打印
void SeqListPrint(SeqList* psl) {
assert(psl);
for (int i = 0; i < psl->size; i++) {
printf("%d ", psl->array[i]);
}
}
// 顺序表头插
void SeqListPushFront(SeqList* psl, SLDataType x) {
assert(psl);
//检查空间是否足够
CheckCapacity(&psl);
int temp_size = psl->size;
while (temp_size > 0) {
psl->array[temp_size] = psl->array[temp_size-1];
temp_size--;
}
psl->array[0] = x;
psl->size++;
}
// 顺序表尾插
void SeqListPushBack(SeqList* psl, SLDataType x) {
assert(psl);
//检查空间是否足够
CheckCapacity(&psl);
psl->array[psl->size] = x;
psl->size++;
}
// 顺序表销毁
void SeqListDestory(SeqList* psl) {
assert(psl);
free(psl->array);
psl->array = NULL;
psl->capicity = 0;
psl->size = 0;
}
// 检查空间,如果满了,进行增容
void CheckCapacity(SeqList** psl) {
if ((*psl)->capicity == 0) {
SLDataType* temp = NULL;
(*psl)->capicity = 4 * sizeof(SLDataType);
temp = (SLDataType)malloc((*psl)->capicity);
if (temp == NULL) {
perror(CheckCapacity);
return 0;
}
(*psl)->array = temp;
return;
}
if ((*psl)->capicity <= (*psl)->size*sizeof(SLDataType)) {
(*psl)->capicity *= 2;
SLDataType* temp = NULL;
//检查开辟是否成功
temp = (SLDataType)realloc((*psl)->array,(*psl)->capicity);
if (temp == NULL) {
perror(CheckCapacity);
return 0;
}
(*psl)->array = temp;
}
}
// 顺序表尾删
void SeqListPopBack(SeqList* psl) {
assert(psl);
psl->size--;
}
// 顺序表头删
void SeqListPopFront(SeqList* psl) {
assert(psl);
int temp_size = 1;
while (temp_size <= psl->size) {
psl->array[temp_size-1] = psl->array[temp_size];
temp_size++;
}
psl->size--;
}
// 顺序表查找
int SeqListFind(SeqList* psl, SLDataType x) {
assert(psl);
//找到返回下标
for (int i = 0; i < psl->size; i++) {
if (psl->array[i] == x) {
return i;
}
}
//没找到返回-1;
return -1;
}
// 顺序表删除pos位置的值
void SeqListErase(SeqList* psl, size_t pos) {
assert(psl);
assert(pos < psl->size);
if (pos >= psl->size) {
printf("删除超出范围限制");
return ;
}
while (pos < psl->size) {
psl->array[pos] = psl->array[pos + 1];
pos++;
}
psl->size--;
}
// 顺序表在pos位置插入x
void SeqListInsert(SeqList* psl, size_t pos, SLDataType x) {
assert(psl);
assert(pos <= psl->size);
CheckCapacity(&psl);
int temp = psl->size;
while (temp > pos) {
psl->array[temp] = psl->array[temp - 1];
temp--;
}
psl->array[pos] = x;
psl->size++;
}
//修改
void SLModify(SeqList* psl, size_t pos, SLDataType x) {
assert(psl);
assert(pos < psl->size);
psl->array[pos] = x;
}
单链表.h
#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* pos, SLTDateType x);
// 单链表 之前插入(难)
void SListInsertBefore(SListNode* pos, SLTDateType x);
// 单链表删除pos位置之后的值
// 分析思考为什么不删除pos位置?
void SListEraseAfter(SListNode* pos);
// 单链表销毁
void SLlistDestory(SListNode* phead);
//单链表删除当前位置
void SListErase(SListNode* pos);
单链表.c
#define _CRT_SECURE_NO_WARNINGS
#include"单链表.h"
SListNode* BuySListNode(SLTDateType x) {
SListNode* temp = (SListNode*)malloc(sizeof(SListNode));
if (temp == NULL) {
perror("malloc fail");
exit(-1);
}
SListNode* newnode = temp;
temp = NULL;
newnode->data = x;
newnode->next = NULL;
return newnode;
}
// 单链表打印
void SListPrint(SListNode* phead) {
SListNode* cur = phead;
while (cur) {
printf("%d->", cur->data);
cur = cur->next;
}
printf("NULL\n");
}
// 单链表的头插
void SListPushFront(SListNode** pphead, SLTDateType x) { //改变一级指针就需要一级指针的地址,所以传入二级指针
assert(pphead);
SListNode* newnode = BuySListNode(x);
newnode->next = *pphead;
*pphead = newnode;
}
// 单链表尾插
void SListPushBack(SListNode** pphead, SLTDateType x) {
assert(pphead);
//单链表不为空
if (* pphead == NULL ) {
SListNode* next = BuySListNode(x);
*pphead = next;
}//单链表为空
else {
SListNode* cur = *pphead;
while (cur->next != NULL) {
cur = cur->next;
}
SListNode* next = BuySListNode(x);
cur->next = next;
}
}
// 单链表头删
void SListPopFront(SListNode** pphead) {
assert(pphead);
if (*pphead == NULL) {
return;
}
SListNode* del = *pphead;
*pphead = (*pphead)->next;
free(del);
del = NULL;
}
// 单链表的尾删
void SListPopBack(SListNode** pphead) {
assert(pphead);
if (*pphead == NULL) {
return;
}
if ((*pphead)->next == NULL) {
free(*pphead);
*pphead = NULL;
return;
}
SListNode* cur = *pphead;
while (cur->next->next != NULL) {
cur = cur->next;
}
free(cur->next);
cur->next = NULL;
}
// 单链表查找
SListNode* SListFind(SListNode* pphead, SLTDateType x) {
assert(pphead);
SListNode* cur = pphead;
while (cur) {
if (x == cur->data) {
printf("找到了\n");
return cur;
}
else {
cur = cur->next;
}
}
return NULL;
}
//单链表在某位置之后插入
void SListInsertAfter(SListNode** pphead,SListNode* pos, SLTDateType x) {
assert(pphead);
if (*pphead == NULL) {
SListPushFront(pphead, x);
return;
}
SListNode* newcode = BuySListNode(x);
newcode->next = pos->next;//注意这两行的顺序
pos->next = newcode;
}
// 单链表 之前插入(难)
void SListInsertBefore(SListNode** pphead, SListNode* pos, SLTDateType x) {
assert(pos);
assert(pphead);
if (*pphead == NULL) {
SListPushFront(pphead, x);
return;
}
//方法一:找到前一项的next
SListNode* cur = *pphead;
if (pos == pphead) {
SListPushFront(pphead, x);
return;
}
while (cur->next != pos) {
cur = cur->next;
//找不到,说明pos传错了
assert(cur);
}
SListNode* newcode = BuySListNode(x);
newcode->next = pos;
cur->next = newcode;
//方法二 顺序法交换
//SListNode* newcode = BuySListNode(pos->data);
//pos->data = x;
}
// 单链表删除pos位置之后的值
// 分析思考为什么不删除pos位置?
void SListEraseAfter(SListNode** pphead, SListNode* pos) {
assert(pphead);
assert(pos);
if (pos->next == NULL) {
SListPopBack(pphead);
return;
}
SListNode* cur = pos->next;
pos->next = pos->next->next;
free(cur);
}
//单链表删除当前位置
void SListErase(SListNode** pphead, SListNode* pos) {
assert(pphead && pos);
if (pos == *pphead) {
SListPopFront(pphead);
return;
}
SListNode* cur = pos->next->next;
pos->data = pos->next->data;
free(pos->next);
pos->next = cur;
}
// 单链表销毁
void SLlistDestory(SListNode** pphead) {
assert(pphead);
SListNode* cur = pphead;
SListNode* next = pphead;
while (cur) {
next = cur->next;
free(cur);
cur = next;
}
pphead = NULL;
}
List.h
#pragma once
#include
#include
#include
typedef int LTDataType;
typedef struct ListNode
{
LTDataType _data;
struct ListNode* next;
struct ListNode* prev;
}ListNode;
// 创建返回链表的头结点.
ListNode* ListCreate();
//双向链表创造一个新节点
ListNode* ListBuyNode(LTDataType x);
// 双向链表打印
void ListPrint(ListNode* plist);
// 双向链表尾插
void ListPushBack(ListNode* plist, LTDataType x);
// 双向链表头插
void ListPushFront(ListNode* plist, LTDataType x);
// 双向链表尾删
void ListPopBack(ListNode* plist);
// 双向链表头删
void ListPopFront(ListNode * plist);
// 双向链表查找
ListNode* ListFind(ListNode* plist, LTDataType x);
// 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x);
// 双向链表删除pos位置的结点
void ListErase(ListNode* pos);
// 双向链表销毁
void ListDestory(ListNode* plist);
List.c
#define _CRT_SECURE_NO_WARNINGS
#include"List.h"
// 创建返回链表的头结点.
ListNode* ListCreate() {
ListNode* ListGuard = (ListNode*)malloc(sizeof(ListNode));
if (ListGuard == NULL) {
perror("ListGuard malloc fai");
exit(-1);
}
ListGuard->next = ListGuard;
ListGuard->prev = ListGuard;
return ListGuard;
}
// 双向链表打印
void ListPrint(ListNode* plist) {
assert(plist);
ListNode* head = plist;
ListNode* cur = head->next;
printf("head<=>");
while (cur != head) {
printf("%d<=>", cur->_data);
cur = cur->next;
}
printf("\n");
}
//双向链表创造一个新节点
ListNode* ListBuyNode(LTDataType x) {
ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));
if (newNode == NULL) {
perror("newNode malloc fail");
exit(-1);
}
newNode->next = NULL;
newNode->prev = NULL;
newNode->_data = x;
return newNode;
}
// 双向链表尾插
void ListPushBack(ListNode* plist, LTDataType x) {
assert(plist);
ListNode* tail = plist->prev;
ListNode* newNode = ListBuyNode(x);
//节点四步走 注意语句顺序!
newNode->next = plist;
plist->prev = newNode;
tail->next = newNode;
newNode->prev = tail;
}
// 双向链表头插
void ListPushFront(ListNode* plist, LTDataType x) {
assert(plist);
ListNode* first = plist->next;
ListNode* newNode = ListBuyNode(x);
//节点四步走 注意语句顺序!
first->prev = newNode;
newNode->next = first;
plist->next = newNode;
newNode->prev = plist;
}
//检查双向列表是否为空
int CheckList(ListNode* plist) {
assert(plist);
//返回“真”为空 返回"假"为非空;
return plist->next == plist->prev;
}
// 双向链表尾删
void ListPopBack(ListNode* plist) {
assert(plist);
assert(!CheckList(plist));
ListNode* tail = plist->prev;
//节点链接
tail->prev->next = plist;
plist->prev = tail->prev;
//释放
free(tail);
}
// 双向链表头删
void ListPopFront(ListNode* plist) {
assert(plist);
assert(!CheckList(plist));
ListNode* first = plist->next;
//节点链接
plist->next = first->next;
first->next->prev = plist;
//释放
free(first);
}
// 双向链表查找
ListNode* ListFind(ListNode* plist, LTDataType x) {
assert(plist);
if (CheckList(plist)) {
printf("链表为NULL,无法查找有效数据\n");
exit(-1);
}
ListNode* cur = plist->next;
while (cur != plist) {
if (cur->_data == x) {
printf("找到啦\n");
return cur;
}
cur = cur->next;
}
return NULL;
}
// 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x) {
assert(pos);
ListNode* first = pos->prev;
ListNode* second = pos;
ListNode* newNode = ListBuyNode(x);
newNode->next = second;
second->prev = newNode;
first->next = newNode;
newNode->prev = first;
}
// 双向链表删除pos位置的结点
void ListErase(ListNode* pos) {
assert(pos);
ListNode* first = pos->prev;
ListNode* del = pos;
ListNode* second = pos->next;
first->next = second;
second->prev = first;
free(del);
}
// 双向链表销毁
void ListDestory(ListNode* plist) {
assert(plist);
ListNode* cur = plist->next;
ListNode* next = NULL;
plist->next = NULL;
while (cur != NULL) {
next = cur->next;
free(cur);
cur = next;
}
printf("销毁成功\n");
}
顺序表
力扣
链表
顺序表优点:1.尾插、尾删效率高。2.可以随机访问。.(了解)3.cpu高速缓存命中率更高(相比链表)顺序表缺点:1.头部中部插入效率低——O(N)2.扩容 ——性能消耗,空间浪费
链表优点:1.任意插入删除都很方便2.扩容——不存在空间浪费(按需申请空间)链表缺点:1.扩容——每次都要申请malloc浪费了时间2.不能随机访问