数据结构之链表
时间: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;
}
}
- 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 数组属性和方法
- k8s代码走读---client-go编程交互基础
- 故障恢复:一次底层超融合故障导致的异常处理
- JavaSE语法
- 链表:听说过两天反转链表又写不出来了?
- 汇总:MySQL 8.0 运维便捷命令
- 链表:一道题目考察了常见的五个操作!
- 性能测试必备知识(11)- 怎么理解内存中的Buffer和Cache?
- 神经网络-感知器(二):Python代码实现
- Kylin、Druid、ClickHouse 核心技术对比
- 在线教育系统开发中,如何实现作业功能字体自定义?
- 保护模式第六讲-IDT表-中断门 陷阱门 任务门
- 跟牛老师一起学WEBGIS——GIS基础(QGIS中数据的创建与编辑)
- Qt信号与槽使用方法最完整总结
- 玩转 PhpStorm 系列(十二):单元测试篇
- 使用Notepad++代替笨拙的Arduino IDE