数据结构及STL.docx
《数据结构及STL.docx》由会员分享,可在线阅读,更多相关《数据结构及STL.docx(81页珍藏版)》请在冰豆网上搜索。
![数据结构及STL.docx](https://file1.bdocx.com/fileroot1/2023-1/31/2207648c-34e4-4da3-8256-b9d2fe4b02bb/2207648c-34e4-4da3-8256-b9d2fe4b02bb1.gif)
数据结构及STL
数据结构
******************
day09
******************
第一课堆栈与队列
1、数据结构的基本概念
(1)逻辑结构
1)集合结构(集):
结构中的元素除了同属一个集外,没有任何联系
2)线性结构(表):
结构中的元素具有一对一的前后关系
3)树型结构(树):
结构中的元素具有一对多的父子关系
4)网状结构(图):
结构中的元素具有多对多的交叉映射关系
(2)物理结构
1)顺序结构(数组):
结构中的元素存放在一段连续的地址空间中。
随机访问方便,空间利用率低,插入删除不方便
2)链式结构(链式):
结构中的元素存放在彼此独立的地址空间中,每个独立的地址空间叫节点。
节点中除了保存数据以外还保存另外一个或几个相关节点的地址。
空间利用率高,插入删除方便,随机访问不方便
(3)逻辑结构和物理结构的关系
表树图
顺序数组顺序树复
链式链表链式树合
2、数据结构的基本运算
(1)创建与销毁
(2)插入与删除
(3)获取与修改
(4)排序与查找
3、堆栈(vistatic.cpp/lstatic.cpp)
(1)基本特征:
后进先出
(2)基本操作:
压入(push),弹出(pop)
(3)实现要点:
初始化空间,栈顶指针,判空判满
【代码:
vistack.cpp】
#include
usingnamespacestd;
//基于顺序表的堆栈
classStack{
public:
//构造过程中分配内存
Stack(size_tsize=10):
m_array(newint[size]),m_size(size),
m_top(0){}
//析构过程中释放内存
~Stack(void){
if(m_array){
delete[]m_array;
m_array=0;
}
}
//压入
voidpush(intdata){
if(full())
throwOverFlow();
m_array[m_top++]=data;
}
//弹出
intpop(void){
if(empty())
throwUnderFlow();
returnm_array[--m_top];
}
//判满
boolfull(void)const{
returnm_top>=m_size;
}
//判空
boolempty(void)const{
return!
m_top;
}
private:
//上溢异常
classOverFlow:
publicexception{
constchar*what(void)constthrow(){
return"堆栈上溢!
";
}
};
//下溢异常
classUnderFlow:
publicexception{
constchar*what(void)constthrow(){
return"堆栈下溢!
";
}
};
int*m_array;//数组
size_tm_size;//容量
size_tm_top;//栈顶
};
voidprintb(unsignedintnumb,intbase){
Stackstack(256);
do{
stack.push(numb%base);
}while(numb/=base);
while(!
stack.empty()){
intdigit=stack.pop();
if(digit<10)
cout<else
cout<}
cout<}
intmain(void){
try{
Stackstack;
for(inti=0;!
stack.full();++i)
stack.push(i);
//stack.push(0);
while(!
stack.empty())
cout<//stack.pop();
}
catch(exception&ex){
cout<return-1;
}
cout<<"输入一个整数:
"<intnumb;
cin>>numb;
cout<<"您想看几进制:
"<intbase;
cin>>base;
cout<<"结果:
";
printb(numb,base);
return0;
}
【代码:
vilstack.cpp】
#include
usingnamespacestd;
//基于链式表的堆栈
classStack{
public:
//构造过程中初始化为空堆栈
Stack(void):
m_top(NULL){}
//析构过程中销毁剩余的节点
~Stack(void){
for(Node*next;m_top;m_top=next){
next=m_top->m_next;
deletem_top;
}
}
//压入
voidpush(intdata){
/*
Node*node=newNode;
node->m_data=data;
node->m_next=m_top;
m_top=node;*/
m_top=newNode(data,m_top);
}
//弹出
intpop(void){
if(empty())
throwUnjjderFlow();
intdata=m_top->m_data;
Node*next=m_top->m_next;
deletem_top;
m_top=next;
returndata;
}
//判空
boolempty(void)const{
return!
m_top;
}
private:
//下溢异常
classUnderFlow:
publicexception{
constchar*what(void)constthrow(){
return"堆栈下溢!
";
}
};
//节点
classNode{
public:
Node(intdata=0,Node*next=NULL):
m_data(data),m_next(next){}
intm_data;//数据
Node*m_next;//后指针
};
Node*m_top;//栈顶
};
intmain(void){
try{
Stackstack;
for(inti=0;i<10;++i)
stack.push(i);
while(!
stack.empty())
cout<//stack.pop();
}
catch(exception&ex){
cout<return-1;
}
return0;
}
***********************************************************
4、队列(viq.cpp/q1.cpp)
(1)基本特征:
先进先出
(2)基本操作:
压入(push),弹出(pop)
(3)实现要点:
初始化空间,从前端(front)弹出,从后端(rear)压入,循环使用,判空判满
【代码:
viq.cpp】
#include
#include"lstack.h"
usingnamespacestd;
//基于堆栈的队列
classQueue{
public:
//压入
voidpush(intdata){
m_i.push(data);
}
//弹出
intpop(void){
if(m_o.empty()){
if(m_i.empty())
throwunderflow_error("队列下溢!
");
while(!
m_i.empty())
m_o.push(m_i.pop());
}
returnm_o.pop();
}
//判空
boolempty(void)const{
returnm_i.empty()&&m_o.empty();
}
private:
Stackm_i;//输入栈
Stackm_o;//输出栈
};
intmain(void){
try{
Queuequeue;
for(inti=0;i<10;++i)
queue.push(i);
cout<cout<cout<cout<cout<queue.push(10);
queue.push(11);
queue.push(12);
while(!
queue.empty())
cout<}
catch(exception&ex){
cout<return-1;
}
return0;
}
【代码:
viq1.cpp】
#include
usingnamespacestd;
//基于顺序表的队列
classQueue{
public:
//构造过程中分配内存
Queue(size_tsize=5):
m_array(newint[size]),m_size(size),
m_rear(0),m_font(0),m_count(0){}
~Queue(void){
if(m_array){
delete[]m_array;
m_array=NULL;
}
}
//压入
voidpush(intdata){
if(full())
throwoverflow();
if(m_rear>=m_size)
m_rear=0;
++m_count;
m_array[m_rear++]=data;
}
//弹出
intpop(void){
if(empty())
throwunderflow();
if(m_font>=m_size)
m_font=0;
--m_count;
returnm_array[m_font++];
}
//判空
boolempty()const{
return!
m_count;
}
//判满
boolfull(){
returnm_count==m_size;
}
private:
//上溢异常
classoverflow:
publicexception{
constchar*what(void)constthrow(){
return"队列上溢!
";
}
};
//下溢异常
classunderflow:
publicexception{
constchar*what(void)constthrow(){
return"队列下溢!
";
}
};
int*m_array;
size_tm_size;//容量
size_tm_rear;
size_tm_font;
size_tm_count;
};
intmain()
{
try{
Queuequeue;
queue.push(10);
queue.push(20);
queue.push(30);
queue.push(40);
queue.push(50);
//queue.push(60);
cout<queue.push(60);
cout<queue.push(70);
cout<cout<cout<cout<}
catch(exception&ex){
cout<return-1;
}
return0;
}
【思考题:
如何用堆栈来实现队列?
(vilstatic2.cpp)】
#include//用堆栈来实现队列
#include"lstatic.h"
usingnamespacestd;
classQueue{
public:
//压入
voidpush(intdata){
m_i.push(data);
}
//弹出
intpop(){
if(m_o.empty()){
if(m_i.empty())
throwunderflow_error("队列下溢!
");
while(!
m_i.empty())
m_o.push(m_i.pop());
}
returnm_o.pop();
}
//判空
boolempty()const{
returnm_i.empty()&&m_o.empty();
}
private:
stackm_i;//输入栈
stackm_o;//输出栈
};
intmain()
{
try{
Queuequeue;
for(inti=0;i<10;++i)
queue.push(i);
cout<cout<cout<cout<cout<cout<}
catch(exception&ex){
cout<}
}
5、链表
(1)基本特征:
内存中不连续的节点序列,彼此之间通过指针相互关联,前指针(prev)指向前节点,后指针(next)指向后节点
(2)基本特征:
追加、插入、删除、遍历
(3)实现要点:
void讲故事(void){
从前有座山;
山里有个庙;
庙里有个老和尚;
if(老和尚圆寂了)
return;
讲故事();
}
6、二叉树(vibstree.cpp)
(1)基本特征
1)树型结构的最简模型,每个节点最多有两个子节点
2)单根,除根节点外每个节点有且只有一个父节点,整棵树只有一个根节点
3)递归结构,用递归处理二叉树问题可以简化算法
(2)基本操作
1)生成
2)遍历
D-L-R:
前序遍历L-D-R:
中序遍历L-R-D:
后序遍历
有序二叉树(二叉搜索树):
L<=D<=R(左小右大)
507020604030109080
50
/\
/----\
20|70
/\/\
10406090
//
3080
/
10
中序遍历:
102030405060708090
【代码:
vibstree.cpp】
include
usingnamespacestd;
//有序二叉树(搜索二叉树)
classTree{
public:
//构造函数过程中初始化为空树
Tree(void):
m_root(NULL),m_size(0){}
//析构过程中销毁剩余节点
~Tree(void){
clear();
}
//插入数据
voidinsert(intdate){
insert(newNode(date),m_root);
++m_size;
}
//删除第一个匹配的数据,不存在返回false
boolerase(intdate){
Node*&node=find(date,m_root);
if(node){
//左子树插入右子树
insert(node->m_left,node->m_right);
Node*temp=node;
//右提升
node=node->m_right;
deletetemp;
--m_size;
returntrue;
}
returnfalse;
}
//删除所有匹配数据
voidremove(intdate){
while(erase(date));
}
//清空树
voidclear(void){
clear(m_root);
m_size=0;
}
//将所有的_old替换为_new
voidupdate(int_old,int_new){
while(erase(_old))
insert(_new);
}
//判断date是否存在
boolfind(intdate){
returnfind(date,m_root)!
=NULL;
}
//中序遍历
voidtravel(){
travel(m_root);
cout<}
//获取树高
size_theight(){
returnheight(m_root);
}
//获取大小
size_tsize(void){
returnm_size;
}
private:
//节点
classNode{
public:
Node(intdate):
m_date(date),m_left(NULL),m_right(NULL){}
intm_date;//数据
Node*m_left;//左树
Node*m_right;//右树
};
voidinsert(Node*node,Node*&tree){
if(!
tree)
tree=node;
elseif(node){
if(node->m_datem_date)
insert(node,tree->m_left);
else
insert(node,tree->m_right);
}
}
//返回子树tree中值与date相匹配的节点的父节中指向该节点的成员变量的别名
Node*&find(intdate,Node*&tree){
if(!
tree)
returntree;
else
if(date==tree->m_date)
returntree;
else
if(datem_date)
returnfind(date,tree->m_left);
else
returnfind(date,tree->m_right);
}
voidclear(Node*&tree){
if(tree){
clear(tree->m_left);
clear(tree->m_right);
deletetree;
tree=NULL;
}
}
voidtravel(Node*tree){
if(tree){
travel(tree->m_left);
cout<m_date<<'';
travel(tree->m_right);
}
}
size_theight(Node*tree){
if(tree){
size_tlh=height(tree->m_left);
size_trh=height(tree->m_right);
return(lh>rh?
lh:
rh)+1;
}
return0;
}
Node*m_root;//树根
size_tm_size;//大小
};
intmain()
{
Treetree;
tree.insert(50);
tree.insert(70);
tree.insert(20);
tree.insert(60);
tree.insert(40);
tree.insert(30);
tree.insert(10);