链式存储的特点和核心操作逻辑
逻辑上连续
顺序存储 连续物理内存
链式 物理上不连续 增加 元素逻辑的关系
存储结构特点
元素里面包含 数据+关系
顺序存储维护 整个表的首地址
存储密度 高
链式存储维护 表内容的首结点,首结点逐个寻找其他节点
存储密度 不高
//链式结点
//单链表
struct node{
int data;
struct node *next;
}
//双链表
struct node{
int data;
struct node *left;
struct node *right;
}
操作算法
在第二个位置上,进行插入操作时,如果索引指针指向第二个节点,无法进行后续操作
单链表中,一旦索引指针往前走一步,之前的元素就再也找不到
一旦把节点的next赋新值,之前的下一个元素的关系,就断开
1.插入操作
node->next=p->next;
p->next=node;
先处理新结点,再处理老结点
2.删除操作
删除A元素,站在A元素的前一个元素上,才能删除A元素
备份 备份A
tmp=p->next;
p->next=tmp->next;(p->next=p->next->next;)
free(tmp);
3.遍历
找到某个结点的next等于null
p
while(p){
//处理p所指向的值
p=p->next;
}
单链表找最大值
int max = 0;
p = xxx;
while (p) {
if (p->value > max) {
max = p->value;
}
p = p->next;
}
max ?第二种遍历,看下一个元素情况
p=xxx;
while(p->next){
if(p->next->value==2){
break;
}
p=p->next;
}
单链表的实现
结构操作:
申请一个结构的头 存储数据的首地址,以及这个结构的其他参数
结构头里面包含一个区域,指向真实的数据
带头结点(推荐)
//linkList.h
#ifndef DATA_STRUCTURE_LINKLIST_H
#define DATA_STRUCTURE_LINKLIST_H
//单链表,带头结点的标头
//节点
typedef int Element;
typedef struct node{
Element ele; //结点中的数据
node *next;
}Node;
//表头
typedef struct{
Node head;
int len; //记录表的长度
}LinkList;
//创建一个表头
LinkList *createLinkList();
//删除表头
void releaseLinkList(LinkList *linkList);
//插入结点
int InsertLinkList(LinkList *linkList,int pos,Element e);
//删除结点
int deleteLinkList(LinkList *linkList,Element e);
// 打印链表
void showLinkList(LinkList *linkList);
#endif //DATA_STRUCTURE_LINKLIST_H
//linkList.cpp
#include "linkList.h"
#include<iostream>
LinkList *createLinkList(){
LinkList *link=new LinkList ; //创建表头
link->head.ele=0x00; //初始化表头里面的内容
link->head.next= nullptr;
link->len=0;
return link; //返回指向表头的指针
}
void releaseLinkList(LinkList *linkList){
int cnt=0; //用来统计被删除的结点数
if(linkList){
Node *node = &linkList->head; //用一个结点指针指向表头里的头结点
while (node->next) { //当有下一个结点存在使,一直循环
Node *tmp = node->next; //以下是删除结点操作
node->next = tmp->next;
delete tmp;
cnt++;
}
std::cout<<"释放了"<<cnt<<"个结点"<<std::endl;
delete linkList; //释放表头
}
}
int InsertLinkList(LinkList *linkList,int pos,Element e){
if(pos<1&&pos>linkList->len){ //判断插入结点的位置是否为有效
std::cout<<"插入位置pos无效"<<std::endl;
return -1;
}
int cnt=0; //用来和判断结点位置pos是否到达
Node *tmp=&linkList->head; //指向表头的节点指针
while(tmp&&cnt<(pos-1)){ //将节点指针tmp,移动到指向pos位置前一个节点
tmp=tmp->next;
cnt++;
}
Node *new_node=new Node ; //创建新结点,后面是给新结点赋值,和完成插入新结点的具体操作
new_node->ele=e;
new_node->next=tmp->next;
tmp->next=new_node;
linkList->len++;
}
int deleteLinkList(LinkList *linkList,Element e){
//找到e元素的前一个位置
Node *node=&linkList->head;
while(node->next&&node->next->ele!=e){ //判断当前结点的下一个结点的值是否为要删除的值
node=node->next;
}
if(node->next== nullptr){ //找不到要删除的值,退出函数
std::cout<<"找不到"<<std::endl;
return -1;
}
//利用删除备份思想
Node *tmp=node->next; //执行删除操作
node->next=tmp->next;
delete tmp;
linkList->len--;
return 0;
}
void showLinkList(LinkList *linkList){
Node *node=linkList->head.next;
while(node){
std::cout<<node->ele<<' ';
node=node->next;
}
std::cout<<std::endl;
}
#include "linkList.h"
#include <iostream>
int main(){
LinkList *link=createLinkList();
if(link== nullptr){
return -1;
}
// 插入节点
for (int i = 0; i < 5; ++i) { // 链表的倒序
InsertLinkList(link, 1, i+100);
}
showLinkList(link);
std::cout<<"============================="<<std::endl;
deleteLinkList(link, 102);
showLinkList(link);
releaseLinkList(link);
return 0;
}