数据结构之链表
时间:2022-04-26
本文章向大家介绍数据结构之链表,主要内容包括一、概念、二、代码、(2)有哨兵的情况、三、练习、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。
一、概念
(1)数组的线性序是由数组的下标决定的,链表中的顺序是由各对象中的指针所决定的
(2)链表结点结构
node *prev;
node *next;
int key;
(3)链表结点
node *head;
node *nil;//哨兵
(4)对链表的操作
LIST-SEARCH(L, k)
LIST-INSERT(L, x)
LIST-DELETE(L, x)
(5)哨兵是个哑对象,可以简化边界条件
二、代码
(1)没有哨兵的情况
//链表结点结构
struct node
{
node *pre;
node *next;
int key;
//构造函数
node(int x):pre(NULL),next(NULL),key(x){}
};
//链表结构
struct List
{
node *head;
List():head(NULL){}
};
//打印
void List_Print(List *L)
{
node *p = L->head;
while(p)
{
cout<<p->key<<' ';
p = p->next;
}
cout<<endl;
}
//搜索,找出L中第一个关键字为k的结点,没有则返回NULL
node *List_Search(List *L, int k)
{
node *x = L->head;
while(x != NULL && x->key!=k)
x = x->next;
return x;
}
//插入
void List_Insert(List *L, node *x)
{
//插入到表的前端
x->next = L->head;
if(L->head != NULL)
L->head->pre = x;
L->head = x;
x->pre = NULL;
}
//删除
void List_Delete(List *L, node* x)
{
if(x->pre != NULL)
x->pre->next = x->next;
else
L->head = x->next;
if(x->next != NULL)
x->next->pre = x->pre;
delete x;
}
//链表结点结构
struct node
{
node *pre;
node *next;
int key;
//构造函数
node(int x):pre(NULL),next(NULL),key(x){}
};
//链表结构
struct List
{
node *head;
List():head(NULL){}
};
//打印
void List_Print(List *L)
{
node *p = L->head;
while(p)
{
cout<<p->key<<' ';
p = p->next;
}
cout<<endl;
}
//搜索,找出L中第一个关键字为k的结点,没有则返回NULL
node *List_Search(List *L, int k)
{
node *x = L->head;
while(x != NULL && x->key!=k)
x = x->next;
return x;
}
//插入
void List_Insert(List *L, node *x)
{
//插入到表的前端
x->next = L->head;
if(L->head != NULL)
L->head->pre = x;
L->head = x;
x->pre = NULL;
}
//删除
void List_Delete(List *L, node* x)
{
if(x->pre != NULL)
x->pre->next = x->next;
else
L->head = x->next;
if(x->next != NULL)
x->next->pre = x->pre;
delete x;
}
(2)有哨兵的情况
//链表结点结构
struct node
{
node *pre;
node *next;
int key;
//构造函数
node(int x):pre(NULL),next(NULL),key(x){}
};
//链表结构
struct List
{
node *nil;//哨兵
List()
{
nil = new node(0);
nil->next = nil;
nil->pre = nil;
}
};
//打印
void List_Print(List *L)
{
node *p = L->nil->next;
while(p != L->nil)
{
cout<<p->key<<' ';
p = p->next;
}
cout<<endl;
}
//搜索,找出L中第一个关键字为k的结点,没有则返回NULL
node *List_Search(List *L, int k)
{
node *x = L->nil->next;
while(x != L->nil && x->key!=k)
x = x->next;
return x;
}
//插入
void List_Insert(List *L, node *x)
{
//插入到表的前端
x->next = L->nil->next;
L->nil->next->pre = x;
L->nil->next = x;
x->pre = L->nil;
}
//删除
void List_Delete(List *L, node* x)
{
x->pre->next = x->next;
x->next->pre = x->pre;
delete x;
}
//链表结点结构
struct node
{
node *pre;
node *next;
int key;
//构造函数
node(int x):pre(NULL),next(NULL),key(x){}
};
//链表结构
struct List
{
node *nil;//哨兵
List()
{
nil = new node(0);
nil->next = nil;
nil->pre = nil;
}
};
//打印
void List_Print(List *L)
{
node *p = L->nil->next;
while(p != L->nil)
{
cout<<p->key<<' ';
p = p->next;
}
cout<<endl;
}
//搜索,找出L中第一个关键字为k的结点,没有则返回NULL
node *List_Search(List *L, int k)
{
node *x = L->nil->next;
while(x != L->nil && x->key!=k)
x = x->next;
return x;
}
//插入
void List_Insert(List *L, node *x)
{
//插入到表的前端
x->next = L->nil->next;
L->nil->next->pre = x;
L->nil->next = x;
x->pre = L->nil;
}
//删除
void List_Delete(List *L, node* x)
{
x->pre->next = x->next;
x->next->pre = x->pre;
delete x;
}
三、练习
10.2-1
能,能
10.2-2
//结点
struct node
{
node *pre;//为了方便实现出栈操作
node *next;
int key;
node(int x):pre(NULL),next(NULL),key(x){}
};
//链式栈
struct list
{
node *Head;//栈的起始结点
node *Top;//栈顶指针
list(){Head = new node(0);Top = Head;}
};
//打印栈中的元素
void Print(list *L)
{
node *p = L->Head->next;
while(p)
{
cout<<p->key<<' ';
p = p->next;
}
cout<<endl;
}
//入栈
void Push(list *L, int x)
{
//构造一个新的结点
node *A = new node(x);
//链入到栈顶位置,修改指针
L->Top->next = A;
A->pre = L->Top;
L->Top = A;
}
//出栈
int Pop(list *L)
{
if(L->Head == L->Top)
{
cout<<"error:underflow"<<endl;
return -1;
}
//取出栈顶元素
int ret = L->Top->key;
//修改指针
node *A = L->Top;
L->Top = A->pre;
L->Top->next = NULL;
delete A;
return ret;
}
10.2-3
//结点
struct node
{
node *next;
int key;
node(int x):next(NULL),key(x){}
};
//链式队列
struct list
{
node *Head;//头指针
node *Tail;//尾指针
list(){Head = new node(0);Tail = Head;}
};
//打印
void Print(list *L)
{
node *p = L->Head->next;
while(p)
{
cout<<p->key<<' ';
p = p->next;
}
cout<<endl;
}
//入队列
void Enqueue(list *L, int x)
{
//构造一个新的结点
node *A = new node(x);
//链入尾部,修改指针
L->Tail->next = A;
L->Tail = A;
}
//出队列
int Dequeue(list *L)
{
if(L->Head == L->Tail)
{
cout<<"error:underflow"<<endl;
return -1;
}
//取出队头结点,修改指针
node *A = L->Head->next;
int ret = A->key;
L->Head->next = A->next;
if(A == L->Tail)
L->Tail = L->Head;
delete A;
return ret;
}
10.2-4
把哨兵的值置为一个不可能与x相等的值
10.2-1
能,能
10.2-2
//结点
struct node
{
node *pre;//为了方便实现出栈操作
node *next;
int key;
node(int x):pre(NULL),next(NULL),key(x){}
};
//链式栈
struct list
{
node *Head;//栈的起始结点
node *Top;//栈顶指针
list(){Head = new node(0);Top = Head;}
};
//打印栈中的元素
void Print(list *L)
{
node *p = L->Head->next;
while(p)
{
cout<<p->key<<' ';
p = p->next;
}
cout<<endl;
}
//入栈
void Push(list *L, int x)
{
//构造一个新的结点
node *A = new node(x);
//链入到栈顶位置,修改指针
L->Top->next = A;
A->pre = L->Top;
L->Top = A;
}
//出栈
int Pop(list *L)
{
if(L->Head == L->Top)
{
cout<<"error:underflow"<<endl;
return -1;
}
//取出栈顶元素
int ret = L->Top->key;
//修改指针
node *A = L->Top;
L->Top = A->pre;
L->Top->next = NULL;
delete A;
return ret;
}
10.2-3
//结点
struct node
{
node *next;
int key;
node(int x):next(NULL),key(x){}
};
//链式队列
struct list
{
node *Head;//头指针
node *Tail;//尾指针
list(){Head = new node(0);Tail = Head;}
};
//打印
void Print(list *L)
{
node *p = L->Head->next;
while(p)
{
cout<<p->key<<' ';
p = p->next;
}
cout<<endl;
}
//入队列
void Enqueue(list *L, int x)
{
//构造一个新的结点
node *A = new node(x);
//链入尾部,修改指针
L->Tail->next = A;
L->Tail = A;
}
//出队列
int Dequeue(list *L)
{
if(L->Head == L->Tail)
{
cout<<"error:underflow"<<endl;
return -1;
}
//取出队头结点,修改指针
node *A = L->Head->next;
int ret = A->key;
L->Head->next = A->next;
if(A == L->Tail)
L->Tail = L->Head;
delete A;
return ret;
}
10.2-4
把哨兵的值置为一个不可能与x相等的值
10.2-5
见算法导论 10.2-5 环形链表实现字典操作INSERT、DELETE、SEARCH
10.2-6
使用带尾指针的链表,令A的尾指针为tail,tail->next=B
10.2-7
//逆转
void Reverse(list *L)
{
node *p = NULL, *q = L->Head, *r;
//依次修改指针,让q是p->next,令q->next=p
while(1)
{
r = q->next;
q->next = p;
if(r == NULL)
{
L->Head = q;
break;
}
p = q;
q = r;
}
}
- 点击块,让小块动起来 - 函数封装
- 玩玩文本挖掘-wordcloud、主题模型与文本分类
- Typecho 前台 getshell 漏洞分析
- 关于其他选择器以及选择器优先级详解
- 2016.05 第二周 群问题分享
- MyFlash——美团点评的开源MySQL闪回工具
- R语言关联规则可视化:扩展包arulesViz的介绍
- JS设置标签的内容和样式
- 大圣魔方——美团点评酒旅BI报表工具平台开发实践
- 详析获取标签
- 深度学习及AR在移动端打车场景下的应用
- R案例操作:RQDA和tm包结合进行文本挖掘
- 用Vue.js开发微信小程序:开源框架mpvue解析
- 分类模型的性能评估——以SAS Logistic回归为例: 混淆矩阵
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 【测试】 Java如何优雅的生成测试数据
- Spring事物的传播行为案例分析
- Ingress-nginx灰度发布功能详解
- [885]Tensorflow设置CUDA_VISIBLE_DEVICES来控制GPU的使用
- Windows10:启用或禁用休眠、保留的存储
- 基于Vue SEO的四种方案
- 一道SQL问题,你来试试的?
- 利用DNSLOG测试Fastjson远程命令执行漏洞
- goldengate classic模式在空闲数据库上抽取和应用数据延迟问题
- gorm jion查询映射(扫描scan)到新的结构体,必须使用select规定字段,与xorm的jion对比
- Spark UDF1 返回复杂结构
- Docker 部署Registry私有仓库+Harbor私有仓库
- goldengate同步无主键无唯一索引表的问题以及解决方案
- goldengate同步无主键无唯一索引表的问题以及解决方案--更新关于附加日志
- 分布式任务调度平台 → XXL-JOB 实战