🌈个人主页: 会编辑的果子君
💫个人格言:"成为自己未来的主人~"
顺序表的问题和思考
中间/头部的插入删除,时间复杂度为O(N)
增容需要申请新空间,拷贝数据,释放旧空间,会有不小的消耗
增容一般是呈2倍的增长,势必会有一定的空间浪费,例如当前容量为100,满了以后增容到200,但是我们只插入了五个数据,后面就没有数据插入了,那么就浪费了95个数据空间。
那,我们应该如何解决上面的问题呢?
是否存在一种数据结构,能够解决以上顺序表表现出来的问题,
中间/头部的插入删除,可以一步到位,不需要挪动数据
不需要扩容
不会造成空间浪费
当然有,这就是链表
链表和顺序表都是线性表
线性表的逻辑结构一定是线性的,物理结构不一定是线性的,
而链表,物理结构一定不是线性的
链表是由一个一个的节点(结点)组成的。
一个节点由两个部分组成:要存储的数据+指针(结构体指针)
cpp
struct SListNode {
int data;
struct SListNode* next;
};
这个就是节点结构的定义
cpp
typedef int SLDataType;
typedef struct SListNode {
SLDataType data;
struct SListNode* next;
}SLTNode;
//typedef struct SListNode SLTNode;
链表的打印:
cpp
#include"SList.h"
void SLTPrint(SLTNode* phead) {
SLTNode* pcur = phead;
while (pcur) {
printf("%d->", pcur->data);
pcur = pcur->next;
}
printf("NULL\n");
}
cpp
void SListTest01() {
//一般不会这样去创建链表,这里只是为了更好的给大家展示打印的过程
SLTNode* node1 = (SLTNode*)malloc(sizeof(SLTNode));
node1->data = 1;
SLTNode* node2 = (SLTNode*)malloc(sizeof(SLTNode));
node1->data = 2;
SLTNode* node3 = (SLTNode*)malloc(sizeof(SLTNode));
node1->data = 3;
SLTNode* node4 = (SLTNode*)malloc(sizeof(SLTNode));
node1->data = 4;
node1->next = node2;
node2->next = node3;
node3->next = node4;
node4->next = NULL;
SLTNode* plist = node1;
SLTPrint(plist);
}
cpp
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SLDataType;
typedef struct SListNode {
SLDataType data;
struct SListNode* next;
}SLTNode;
//typedef struct SListNode SLTNode;
void SLTPrint(SLTNode* phead);
//链表的头插,尾插
void SLTPushBack(SLTNode** phead, SLDataType x);
void SLTPushFront(SLTNode** phead, SLDataType x);
//链表的头删,尾删
void SLTPopBack(SLTNode** pphead);
void SLTPopFront(SLTNode** pphead);
cpp
#define _CRT_SECURE_NO_WARNINGS
#include"SList.h"
//节点结构的定义
//struct SListNode {
// int data;
// struct SListNode* next;
//};
void SListTest01() {
//一般不会这样去创建链表,这里只是为了更好的给大家展示打印的过程
SLTNode* node1 = (SLTNode*)malloc(sizeof(SLTNode));
node1->data = 1;
SLTNode* node2 = (SLTNode*)malloc(sizeof(SLTNode));
node2->data = 2;
SLTNode* node3 = (SLTNode*)malloc(sizeof(SLTNode));
node3->data = 3;
SLTNode* node4 = (SLTNode*)malloc(sizeof(SLTNode));
node4->data = 4;
node1->next = node2;
node2->next = node3;
node3->next = node4;
node4->next = NULL;
SLTNode* plist = node1;
SLTPrint(plist);
}
void SLIstTest02() {
SLTNode* plist = NULL;
SLTPushBack(&plist, 1);
SLTPushBack(&plist, 2);
SLTPushBack(&plist, 3);
SLTPushBack(&plist, 4);
SLTPrint(plist); //1->2->3->4->NULL
}
int main()
{
//SListTest01();
SLIstTest02();
return 0;
}
cpp
#define _CRT_SECURE_NO_WARNINGS
#include"SList.h"
void SLTPrint(SLTNode* phead) {
SLTNode* pcur = phead;
while (pcur) {
printf("%d->", pcur->data);
pcur = pcur->next;
}
printf("NULL\n");
}
SLTNode* SLTBuyNode(SLDataType x) {
SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
newnode->data = x;
newnode->next = NULL;
return newnode;
}
void SLTPushBack(SLTNode** pphead, SLDataType x) {
assert(pphead);
SLTNode* newnode = SLTBuyNode(x);
//链表为空,新节点作为phead
if (*pphead = NULL) {
*pphead = newnode;
return;
}
//链表不为空,找尾节点
SLTNode* ptail = *pphead;
while (ptail->next) {
ptail = ptail->next;
}
//ptail就是尾节点
ptail->next = newnode;
}
void SLTPushFront(SLTNode** pphead, SLDataType x) {
assert(pphead);
SLTNode* newnode = SLTBuyNode(x);
newnode->next = *pphead;
*pphead = newnode;
}
void SLTPopBack(SLTNode** pphead) {
assert(pphead);
//链表不能为空
assert(*pphead);
//链表不为空,
//链表只有一个节点,有多个节点
if ((*pphead)->next == NULL) {
free(*pphead);
*pphead = NULL;
return;
}
SLTNode* ptail = *pphead;
SLTNode* prev = NULL;
while (ptail->next) {
prev = ptail;
ptail = ptail->next;
}
prev->next = NULL;
//销毁尾节点
free(ptail);
ptail = NULL;
}