数据结构与算法(第三章~第四章)

发布于:2022-11-01 ⋅ 阅读:(396) ⋅ 点赞:(0)

文章目录

第三章:栈和队列

3.1:栈和队列的定义和特点

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.1.1:栈的定义和特点

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.1.2:队列的定义和特点

在这里插入图片描述
在这里插入图片描述

3.2:案例引入

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.3:栈的表示和操作的实现

3.3.1:栈的类型定义

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.3.2:顺序栈的表示与实现

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.3.2.1:顺序栈的初始化

在这里插入图片描述

//算法3.1:顺序栈的初始化
Status InitStack(Sqstack &S)
{//构造一个空栈S
	S.base=new SELemType[MAXSIZE];			//为顺序栈动态分配一个最大容量为MAXSIZE的数组空间
	if(!S.base)	exit(OVERFLOW);				//存储分配失败
	S.top=S.base;							//top初始化为base,空栈
	S.stacksize=MAXSIZE;					//stacksize置为栈的最大容量	MAXSIZE
	return OK;
}

3.3.2.2:顺序栈判断栈是否为空

在这里插入图片描述

//顺序栈判断栈是否为空
Status StackEmpty(SqStack S)
{//若栈为空,返回TRUE,否则返回FALSE
	if(S.top==S.base)
		return TRUE;
	else 
		return FALSE;
}

3.3.2.3:求顺序栈的长度

在这里插入图片描述

//求顺序栈的长度
int StackLength(SqStack S)
{
	return S.top-S.base;
}

3.3.2.4:清空顺序栈

在这里插入图片描述

//清空顺序栈
Status ClearStack(SqStack S)
{
	if(S.base) S.top=S.base;
	return OK;
}

3.3.2.5:销毁顺序栈

在这里插入图片描述

//销毁顺序栈
Status DestroyStack(SqStack &S)
{
	if(s.base)
	{
		delete S.base;
		S.stacksize=0;
		S.base=S.top=NULL;
	}
	return OK;
}	

3.3.2.6:顺序栈的入栈

在这里插入图片描述

//算法3.2 顺序栈的入栈
Status Push(SqStack &S SElemType e)
{//插入元素e为新的栈顶元素
	if(S.top-S.base==S.stacksize)	return ERROR;		//栈满
	*S.top++=e;						//将元素e压入栈顶,栈顶指针加1  (*S.top=e; S.top++;)
	return OK;
}

3.3.2.7:顺序栈的出栈

在这里插入图片描述

//顺序栈的出栈
Status Pop(SqStack &S,SElemType &e)
{//删除S的栈顶元素,用e返回其值
	if(S.top-S.base==S.stacksize)	return ERROR;	//栈空
	e=*--S.top;										//栈顶指针减1,将栈顶元素赋给e
	return OK;
}

3.3.3:链栈的表示和实现

在这里插入图片描述

在这里插入图片描述

3.3.3.1:链栈的初始化

//算法3.5 链栈的初始化
Status InitStack(LinkStack &S)
{//构造一个空栈S,栈顶指针置空
	S=NULL;
	return OK;
}

3.3.3.2:链栈的入栈

在这里插入图片描述

//算法3.6 链栈的入栈
Status Push(LinkStack &S,SElemType e)
{//在栈顶插入元素e
	p=new StackNode;		//生成新结点
	p->data=e;				//将新结点数据置为e
	p->next=S;				//将新结点插入栈顶
	S=p;					//修改栈顶指针为p
	return OK;
}

3.3.3.3:链栈的出栈

在这里插入图片描述

//算法3.7 链栈的出栈
Status Pop(LinkStack &S,SElemType &e)
{//删除S的栈顶元素,用e返回其值
	if(S==NULL) return ERROR;		//栈空
	e=S->data;						//将栈顶元素赋给e
	p=S;							//用p临时保存栈顶元素空间,以备释放
	S=S->next;						//修改栈顶元素
	delete p;						//释放原栈顶元素空间
	return OK;
}

3.3.3.4:取栈顶元素

在这里插入图片描述


//算法3.8 取栈顶元素
SElemType GetTop(LinkStack S)
{//返回S的栈顶元素,不修改栈顶指针
	if(S!=NULL)				//栈非空
		return S->data;		//返回栈顶元素的值,栈顶指针不变
}

3.4:栈与递归

在这里插入图片描述

3.4.1:采用递归算法解决的问题

在这里插入图片描述
在这里插入图片描述

//算法3.9 遍历输出链表中各个结点的递归算法
void TraverseList(LinkList p)
{
	if(p==NULL) return;				//递归终止
	else 
	{
		count<<p->data<<endl;		//输出当前结点的数据域
		TraverseList(L->next);		//p指向后继结点继续递归
	}
}
//简化

void TraverseList(LinkList p)
{
	if(p)				
	{
		count<<p->data<<endl;		
		TraverseList(L->next);		
	}
}
//算法3.10 Hanoi塔问题得递归算法
void Hanoi(int n,char A,char B,char C)
{//将塔座A上的n个圆盘按规则搬到C上,B座辅助塔
	if(n==1) move(A,1,c);			//将编号为1的圆盘从A移动到C
	else							
	{
		Hanoi(n-1,A,C,B);			//将A上编号为1至n-1的圆盘移动到B,C座辅助塔
		move(A,n,C);				//将编号为n的圆盘从A移动到C
		Hanoi(n-1,B,A,c);			//将B上编号为1至n-1的圆盘移动到C,A座辅助塔
	}
}

在这里插入图片描述
在这里插入图片描述

3.4.2:递归过程和递归工作栈

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.4.3:递归算法的效率分析

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.4.4:利用栈将递归转换为非递归的方法

在这里插入图片描述
在这里插入图片描述

3.5:队列的表示和操作实现

3.5.1:队列的类型定义

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

3.5.2:循环队列------队列的顺序表示与实现

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

//队列的顺序存储结构
#define MAXQSIZE 100		//队列可能达到的最大长度
typedef struct				
{
	QElemType *base;		//存储空间的基地址
	int front;				//头指针
	int rear;				//尾指针
}SqQueue;

3.5.2.1:队列的初始化

在这里插入图片描述

//算法3.1 循环队列的初始化
Status	InitQueue(SqQueue &Q)
{//构造一个空队列
	Q.base=new QElemType[MAXQSIZE];			//为队列分配一个最大容量为MAXQSIZE的数组空间
	if(!Q.base)	exit(OVERFLOW);				//存储分配失败
	Q.front=Q.rear=0;						//头指针和尾指针置为0,队列为空
	return OK;
}

3.5.2.2:求循环队列的长度

在这里插入图片描述

//算法3.12 求循环队列的长度
int QueueLength(SqQueue Q)
{//返回Q的元素个数,即队列的长度
	return(Q.rear-Q.front+MAXQSIZE)%MAXQSIZE;
}

3.5.2.3:循环队列的入队

在这里插入图片描述

在这里插入图片描述

//算法3.13 循环队列的入队
Status EnQueue(SqQueue &Q,QElemType e)
{//插入元素e为Q的新的队尾元素
	if((Q.rear+1)%MAXQSIZE==Q.front)	//尾指针在循环意义上加1后等于头指针,表明队满
		return REEOR;
	Q.base[Q.rear]=e;					//新元素插入队尾
	Q.rear=(Q.rear+1)%MASQSIZE;			//队尾指针加1
	return OK;
}

3.5.2.4:循环队列的出队

在这里插入图片描述
在这里插入图片描述

//算法3.14 循环队列的出队
Status DeQueue(SqQueue &Q,QElemType &e)
{//删除Q的队头元素,用e返回其值
	if(Q.front==Q.rear) return ERROR;		//队空
	e=Q.base[Q.front];						//保存队头元素
	Q.front=(Q.front+1)%MAXQSIZE;			//队头指针加1
	return OK;
}

3.5.2.5:取循环队列的队头元素

在这里插入图片描述

//算法3.15 取循环队列的队头元素
SElemType GetHead(SqQueue Q)
{//返回Q的队头元素
	if(Q.front!Q.rear)				//队列非空
		return Q.base[Q.front];		//返回队头元素的值,队头指针不变
}

3.5.3:链队------队列的链式表示与实现

3.5.3.1:链队的类型定义

在这里插入图片描述
在这里插入图片描述

//队列的链式存储结构
typedef struct QNode
{
	QElemType data;
	struct QNode *next;
}QNode, *QueuePtr;
typedef struct
{
	QueuePtr front;			//队头指针
	QueuePtr rear;			//队尾指针
}LinkQueue;

3.5.3.2:链队的初始化

在这里插入图片描述


//算法 3.16 链队的初始化
Status InitQueue(LinkQueue &Q)
{//构造一个空队列Q
	Q.front=Q.rear=new QNode;		//生成新结点作为头结点,队头和队尾指针指向此结点
	Q.front->next=NULL;				//头指针的指针域置空
	return OK;
}

3.5.3.3:销毁链队列(补充)

在这里插入图片描述
在这里插入图片描述

//销毁链队列
Status DestroyQueue(LinkQueue &Q)
{
	while(Q.front)
	{
		p=Q.front->next;
		free(Q.front);
		Q.front=p;
	}
}

3.5.3.4:链队的入队

在这里插入图片描述

//算法3.17 链队的入队
Status EnQueue(LinkQueue &Q,QElemType e)
{//插入元素e为Q的新的队尾元素
	p=new QNode;					//为入队元素分配结点空间,用指针p指向
	p->data=e;						//将新结点数据域置为e
	p->next=NULL;Q.rear->next=p;	//将新结点插入到队尾
	Q.rear=p;						//修改队尾指针
	return OK;
}

3.5.3.5:链队的出队

在这里插入图片描述
在这里插入图片描述

//算法3.18 链队的出队
Status DeQueue(LinkQueue &Q,QElemType &e)
{//删除Q的队头元素,用e返回其值
	if(Q.front==Q.rear)	return ERROR;		//若队列空,则返回ERROE
	p=Q.front->next;						//p指向队头元素
	e=p->data;								//e保存队头元素的值
	Q.front->next=p->next;					//修改头指针的指针域
	if(Q.rear==p) Q.rear=Q.front;			//最后一个元素被删,队尾指针指向头指针
	delete p;								//释放原队头元素的空间
	return OK;
}

3.5.3.6:取队头元素

在这里插入图片描述

//算法3.19 取链队的队头元素
SElemType GetHead(LinkQueue Q)
{//返回Q的队头元素,不修改队头指针
	if(Q.front!=Q.rear)					//队列非空
		return Q.front->next->data;		//返回队头元素的值,队头指针不变
}

第四章:串,数组和广义表

4.1:串的定义

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.2:案例引入

请添加图片描述
在这里插入图片描述

4.3:串的类型定义,存储结构及其运算

4.3.1:串的抽象类型定义

在这里插入图片描述
在这里插入图片描述

4.3.2:串的存储结构

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

//串的定长顺序存储结构
#define MAXSIZE 255			//串的最大长度
typedef struct		
{
	char ch[MAXLEN+1];		//存储串的以为数组
	int length;				//串的当前长度
}SString;
//串的堆式顺序存储结构
typedef struct
{
	char *ch;			//若是非空串,则按串长分配存储区,否则ch为NULL
	int length;			//串的当前长度
}HString;
//串的堆式顺序存储结构
typedef struct
{
	char *ch;			//若是非空串,则按串长分配存储区,否则ch为NULL
	int length;			//串的当前长度
}HString;

//串的链式存储结构			//可有用户定义的块的大小
#define CHUNKSIZE			
typedef struct Chunk
{
	char ch[CHUNKSIZE]:
	struct Chunk *next;
}Chunk;
typedef struct
{
	Chunk *head,*tail;		//串的头和尾指针
	int length;				//串的当前长度
}LSting;

4.3.3:串的模式匹配算法

在这里插入图片描述

4.3.3.1:BF算法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

//算法 4.1 BF算法
int Index BF(SString S,SString T,int pos)
{//返回模式T在主串S中第pos个字符开始第一次出现的位置,若不存在,则返回值为1
	//其中,T非空,1<=pos<=S.length
	i=pos; j=1;							//初始化
	while(i<S.length && j<=T.length)	//两个串均未比较到串尾
	{
		if(S.ch[i]==T.ch[j])			//继续比较后继字符
		{
			++i;
			++j;
		}
		else							//指针后退重新开始匹配
		{
			i=i-j+2;
			j=1;
		}
	}
	if(j>T.length)	return i-T.length;	//匹配成功
	else	return 0;					//匹配失败
}
 

4.3.3.2:KMP算法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

//算法4.2 KMP算法
int Index_KMP(SString S,SString T,int pos)
{//利用模式串T的nex函数求T在主串S中的第pos个字符之后的位置
	//其中,T非空,1<=pos<=S.length
	i=pos;j=1;
	while(i<=S.length && j<=T.length)		//两个串均未比较到串尾
	{
		if(j==0||S.ch[i]==T)				//继续比较后继字符
		{
			++i;
			++j;
		}
		else								//模式串向右移动
		{
			j=nex[j];
		}
	}
	if(j>T.length)	return i-T.length;		//匹配成功
	else	return 0;						//匹配失败
}

//算法4.3计算next函数值

void get_next(SString T,int next[])
{//求模式串T的next函数值并存入数组next
	i=1;next[1]=0;j=0;
	while(i<T.length)
	{
		if(j==0||T.ch[i]==T.ch[j])
		{
			++i;
			++j;
			next[i]=j;
		}
		else 
		{
			j=next[j];
		}
	}
}


//算法4.4 计算next函数的修正值
void get_nextval(SString T,int nextval[j])
{//求模式串T的next函数修正值并存入数组nextval
	i=1;nextval[1]=0;j=0;
	while(i<T.length)
	{
		if(j==0||T.ch[i]==T.ch[j])
		{
			++i;++j;
			if(T.ch[i]!=T.ch[j]) nextval[i]=j;
			else nextval[i]=nextval[j];
		}
		else j=nextval[j];
	}
}

4.4 :数组

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

4.4.1:数组的类型定义

在这里插入图片描述

4.4.2:数组的顺序存储

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.4.3:特殊矩阵的压缩存储

在这里插入图片描述
在这里插入图片描述

4.4.3.1:对称矩阵

在这里插入图片描述
在这里插入图片描述

4.4.3.2:三角矩阵

在这里插入图片描述

4.4.3.3:对角矩阵

在这里插入图片描述
在这里插入图片描述

4.4.3.4:稀疏矩阵

在这里插入图片描述
在这里插入图片描述

4.4.3.4.1:顺序存储结构------三元顺序表

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.4.4.3.2:链式存储结构------十字链表

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.5:广义表

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

4.6:案例分析与实现

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述