数据结构学习笔记_顺序表和链表(C++实现)

线性表

  1. 相同数据类型
  2. 线性表基本操作:初始化、销毁、插入、删除、按值查找、按位查找、求表长、判空等(创销、增删改查),基本操作的输入一般是“&”引用的表,操作后原表会改变。

顺序表

  1. 顺序存储,按地址排列
  2. 顺序表特点:索引方便、存储密度高、拓展容量不方便,插入删除不方便 (需要依次后移或前移)
//静态分配(必须常数个空间)
int a[8];//占用空间 4*8 字节

//动态分配(根据实际变量分配空间)
//c语言
int len = 8;
int* a;
a = (int*) malloc(len * sizeof(int));
free(a);//变量用完后需要销毁
//c++
int* a = new int[len]
delete a;//用完销毁

note:

  1. 动态分配依旧不能随意改变分配的空间大小,但是可以通过另起一片空间,更换头指针的方式改变数组大小。
  2. 动态分配用完记得销毁。
  3. 循序表不方便增删,容量固定,链表不方便查找

单链表

  1. 每个节点包括数据域指向下个节点的指针域
  2. 特点:不用连续空间,方便改变容量、不可索引
//代码仅作参考
//C语言
typedef struct ListNode {
	int val;
	struct ListNode* next;
}ListNode;
head = (ListNode*) malloc(sizeof(ListNode));

//C++
struct ListNode {
	int val;
	struct ListNode* next;
	//初始化列表
	ListNode() : val(0), next(nullptr) {}
    ListNode(int x) : val(x), next(nullptr) {}
    ListNode(int x, ListNode *next) : val(x), next(next) {}
};

ListNode* head;
head->val = 1;
head->next = new ListNode(1);

//尾部插入1个
//遍历到尾部
ListNode* node = head;
while(node->next != nullptr)
	node = node->next;
node->next = new ListNode(1);

//中间插入1个
//先建一个节点next指向node->next的节点,再把node->next指向新建的节点
ListNode* node = head;
for(int i = 0; i < 3; ++i)//按位查找
	node = node->next;
node->next = new ListNode(1, node->next);

//循环头插(链表逆置)
ListNode* node = head;
ListNode* head1 = new ListNode(head->val);//定义一个新链表
while(node->next != nullptr) {
	ListNode* node1 = new ListNode(node->next->val);
	node1->next = head1->next;
	head1->next = node1;
	node = node->next;
}

//删除中间
ListNode* node = head;
for(int i = 0; i < 3; ++i)
	node = node->next;
//删除node->next
ListNode* tmp = node->next;
node->next = node->next->next;
delete tmp;

note:

  1. 已知中间节点,如果要前插一个,则将已知节点复制给一个新建节点插入到已知节点后,然后更改已知节点,删除同理。
  2. 增删改查可以封装成函数,输入用引用格式可以实现改变原链表。

双链表

  1. 可以向前查找,两个节点之间是双向指针
  2. 一个节点包含数据域和前驱指针prior、后继指针next

在这里插入图片描述

//代码仅作参考
struct ListNode {
	int val;
	struct ListNode* prior;
	struct ListNode* next;
	//初始化列表
	ListNode() : val(0), prior(nullptr), next(nullptr) {}
    ListNode(int x) : val(x), prior(nullptr), next(nullptr) {}
    ListNode(int x, ListNode *prior, ListNode *next) : val(x), prior(prior), next(next) {}
};

ListNode* head;
head->val = 1;
head->next = new ListNode(1);

//中间插入1个
//1、先建一个节点,prior指向node,next指向node->next的节点;
//2、node->next-prior指向新建的节点
//3、node->next指向新建的节点(2,3顺序不能换)
ListNode* node = head;
for(int i = 0; i < 3; ++i)//按位查找
	node = node->next;
ListNode* tmp = new ListNode(1, node, node->next);
node->next->prior = tmp;
node->next = tmp;

//删除中间
ListNode* node = head;
for(int i = 0; i < 3; ++i)
	node = node->next;
//删除node->next,更新前后节点指针,再删除
ListNode* tmp = node->next;
node->next->next->prior = node;
node->next = node->next->next;
delete tmp;

note:

  1. 表尾插入需要判断非空

循环链表

  1. 尾结点指向头节点
  2. 循环单链表也可以实现前节点的查找
    在这里插入图片描述

在这里插入图片描述

//代码仅作参考
//初始化
ListNode* head;
head->val = 1;
head->prior = head;
head->next = head;

//判断表尾
ListNode* node = head;
while(node->next != head) {
	node = node->next;
}
//插入和删除参考以上

静态链表

  1. 用数组的方式实现链表
  2. 每个节点包括数据域和游标
  3. 表尾的游标一般为-1
  4. 应用:操作系统的文件分配表FAT
//代码仅作参考
typedef struct ListNode {
	int val;
	int next;
}ListNode[10];//结构体数组

ListNode head;
for(int i = 0; i < 10; ++i) {
	head[i]->next = -2;//还未分配节点
}

head[0]->val = 0;
head[0]->next = 3;
head[head[0]->next]->val = 1;//实际是head[3]
head[head[0]->next]->next = 8;

note:

  1. 增,删操作不用移动元素
  2. 不能随机存取,只能从前往后查找
  3. 容量固定
  4. 初始化静态链表的非节点位置处(还未分配节点的空间)时,游标可以统一自定义为一个数
  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值