1. 基本概念定义
1.1 顺序表 (Sequential List)
顺序表是物理内存连续存储的数据结构,底层通常基于数组实现。其核心特点是:元素在内存中按逻辑顺序依次排列,每个元素的内存地址可通过“起始地址 + 索引×元素大小”直接计算,因此能通过索引快速定位任意元素,是线性表中最基础、最直观的实现方式之一。
1.2 链表 (Linked List)
链表是非连续存储的线性数据结构,由若干个“节点”通过指针(或引用)连接形成序列。每个节点包含两部分:
- 数据域:存储节点的实际业务数据;
- 指针域:存储下一个(或上一个,如双向链表)节点的内存地址,用于维护节点间的逻辑顺序。
由于节点无需连续存储,链表的内存分配更加灵活,可根据数据量动态调整。
2. 核心特性对比
| 特性 | 顺序表 | 链表 |
|---|---|---|
| 存储方式 | 连续内存空间,元素地址连续 | 非连续内存空间,节点通过指针连接 |
| 内存分配 | 支持静态分配(大小固定)或动态一次性分配(初始化时申请整块内存) | 动态按需分配,新增节点时才单独申请内存 |
| 访问方式 | 随机访问,通过索引直接定位(如 a[i]),无需遍历 | 顺序访问,必须从表头(头节点)开始遍历,无法直接跳转到目标节点 |
| 插入/删除效率 | 需移动目标位置前后的元素(例如在中间插入时,需后移后续所有元素),平均时间复杂度 O(n) | 已知目标节点位置时,仅需修改指针指向(无需移动元素),时间复杂度 O(1) |
3. 优缺点分析
3.1 顺序表的优缺点
优点
- 随机访问高效
- 缓存友好
- 空间效率高
缺点
- 大小固定(静态分配)
- 插入/删除低效
- 内存要求高
- 内存浪费
3.2 链表的优缺点
优点
- 动态大小
- 插入/删除高效
- 内存利用率高
缺点
- 随机访问低效
- 空间开销大
- 缓存不友好
4. 适用场景
4.1 顺序表适用场景
- 频繁随机访问的场景
- 对访问速度要求高的场景
4.2 链表适用场景
- 频繁插入/删除的场景
- 内存资源有限的场景
双向链表

栈的操作
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdbool.h>
#define MAX 100
//栈结构体定义
typedef struct stack{
int data[MAX];
int top;
int maxlen;
}Stack,*Stack_p;
//创建堆栈
Stack_p create(){
Stack_p stack=(Stack_p)malloc(sizeof(Stack));
if(NULL!=stack){
stack->maxlen=MAX;
memset(stack->data,0,sizeof(stack->data));
stack->top=-1;
}
return stack;
}
//判满
bool is_full(Stack_p stack){
return stack->top+1==stack->maxlen;
}
//判空
bool is_empty(Stack_p stack){
return stack->top==-1;
}
//压栈
bool push_stack(Stack_p stack,int value){
if(NULL==stack||is_full(stack)) return false;
stack->data[++stack->top]=value;
}
//出栈
bool pop_stack(Stack_p stack){
if(NULL==stack||is_empty(stack)) return false;
stack->top--;
return true;
}
//打印栈
bool print_stack(Stack_p stack){
printf("--------------------------------\n");
for(int i=stack->top;i>=0;i--) printf("%d ",stack->data[i]);
putchar(10);
printf("--------------------------------\n");
}
//栈的销毁
bool destroy_stack(Stack_p *stack){
if(NULL==*stack) return false;
free(*stack);
*stack=NULL;
return true;
}
int main(int argc,const char *argv[]){
//创建栈
Stack_p stack=create();
//压栈
for(int i=1;i<=5;i++) push_stack(stack,i);
printf("压栈后还剩%d个元素:\n",stack->top+1);
print_stack(stack);
//弹栈
for(int i=1;i<=4;i++){
pop_stack(stack);
printf("弹栈后还剩%d个元素:\n",stack->top+1);
print_stack(stack);
}
destroy_stack(&stack);
if(NULL==stack) printf("销毁后为NULL\n");
else{
printf("销毁后还剩下%d个元素\n",stack->top+1);
print_stack(stack);
}
print_stack(stack);
return 0;
}

双向循环链表操作
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdbool.h>
#define INF 0x7fffffff
//双向链表结构体定义
typedef struct node{
union{
int len;
int data;
};
struct node *pre,*next;
}Node,*Next;
//创建有头节点的双向链表 ,返回指针
Next create_h(){
Next L=(Next)malloc(sizeof(Node));
if(NULL!=L){
L->len=0;
L->next=L;
L->pre=L;
}
return L;
}
//创建值为datd的双向链表节点
Next create_n(int data){
Next node=(Next)malloc(sizeof(Node));
if(NULL!=node){
node->data=data;
node->next=NULL;
node->pre=NULL;
}
return node;
}
//打印双向链表,输完后自动换行
void print(Next L){
if(NULL!=L){
Next p=L->next;
while(p!=L){
printf("%d ",p->data);
p=p->next;
}
putchar(10);
}
}
//头插法插入值为data的节点
bool insert_h(Next L,int data){
if(NULL==L) return false;
Next p=create_n(data);
if(NULL==p) return false;
p->pre=L;p->next=L->next;
L->next=p;
p->next->pre=p;
L->len++;
return true;
}
//判空
bool isEmpty(Next L){
if(NULL==L) return true;
return L==L->next;
}
//从头开始删除一个节点
bool delete_h(Next L){
if(NULL==L||L==L->next) return false;
Next p=L->next;
p->next->pre=L;
L->next=p->next;
free(p);
return true;
}
//在尾节点插入一个值为value的节点
bool insert_b(Next L,int value){
if(NULL==L) return false;
Next p=L;
while(p->next!=L) p=p->next;
Next node=create_n(value);
if(NULL==node) return false;
L->len++;
node->next=p->next;
node->pre=p;
p->next=node;
return true;;
}
//删除尾节点
bool delete_b(Next L){
if(NULL==L||L==L->next) return false;
Next p=L;
while(p->next->next!=L) p=p->next;
free(p->next);
p->next=L;
L->len--;
return true;
}
int main(int argc,const char *argv[]){
//创建单链表
Next L=create_h();
//头插法插入10个值为i的节点
printf("头插法\n");
for(int i=1;i<=8;i++) insert_h(L,i);
print(L);
//头删法删除三个节点
printf("头删法:\n");
delete_h(L);delete_h(L);delete_h(L);
print(L);
//尾插法插入值为-1,-2两个节点
printf("尾插法:\n");
insert_b(L,-1);insert_b(L,-2);
print(L);
//尾删法删除两个尾节点
printf("尾删法:\n");
delete_b(L),delete_b(L);
print(L);
return 0;
}

8804

被折叠的 条评论
为什么被折叠?



