C语言督学营 中期笔记 (Day5~6)

C语言督学营 中期笔记 (Day5~6),第1张

C语言督学营 中期笔记 (Day5~6)

一研为定

文章目录
  • 第五次 直播 双向链表
    • 双向链表的增删改查
    • 双向链表的删除
  • 第五次 直播 其他链表
    • 循环单链表
    • 静态链表
    • 常见问题
  • 第六次 直播 引用解析、栈与队列
    • 栈的实现
    • 栈的基本 *** 作
    • 队列
    • 循环队列

第五次 直播 双向链表


核心; 注意双向链表的插入次序 ①②③④ 标识

注意:赋值语句的解读 eg: p->next = s ; 的意思为将 s 的值赋给 p->next

双向链表的增删改查
 #include 
#include 

typedef int ElemType;
typedef struct DNode{
	ElemType data;
	struct DNode *prior,*next;//前驱,后继
}DNode,*DlinkList;
//双向链表头插法
DlinkList Dlist_head_insert(DlinkList &DL)
{
	DNode *s;int x;
	DL=(DlinkList)malloc(sizeof(DNode));//带头结点的链表,不带头结点
	DL->next=NULL;
	DL->prior=NULL;
	scanf("%d",&x);//从标准输入读取数据
	//3 4 5 6 7 9999
	while(x!=9999){
		s=(DlinkList)malloc(sizeof(DNode));//申请一个空间空间,强制类型转换
		s->data=x;
		s->next=DL->next;
		if(DL->next!=NULL)//插入第一个结点时,不需要这一步 *** 作
		{
			DL->next->prior=s;
		}
		s->prior=DL;
		DL->next=s;
		scanf("%d",&x);//读取标准输入
	}
	return DL;
}
//双向链表尾插法
DlinkList Dlist_tail_insert(DlinkList &DL)
{
	int x;
	DL=(DlinkList)malloc(sizeof(DNode));//带头节点的链表
	DNode *s,*r=DL;
	DL->prior=NULL;
	//3 4 5 6 7 9999
	scanf("%d",&x);
	while(x!=9999){
		s=(DNode*)malloc(sizeof(DNode));
		s->data=x;
		r->next=s;
		s->prior=r;
		r=s;//r指向新的表尾结点
		scanf("%d",&x);
	}
	r->next=NULL;//尾结点的next指针赋值为NULL
	return DL;
}
//按序号查找结点值
DNode *GetElem(DlinkList DL,int i)
{
	int j=1;
	DNode *p=DL->next;
	if(i==0)
		return DL;
	if(i<1)
		return NULL;
	while(p&&jnext;
		j++;
	}
	return p;
}
//新结点插入第i个位置
bool DListFrontInsert(DlinkList DL,int i,ElemType e)
{
	DlinkList p=GetElem(DL,i-1);
	if(NULL==p)
	{
		return false;
	}
	DlinkList s=(DlinkList)malloc(sizeof(DNode));//为新插入的结点申请空间
	s->data=e;
	s->next=p->next;
	p->next->prior=s;
	s->prior=p;
	p->next=s;
	return true;
}
//删除第i个结点
bool DListDelete(DlinkList DL,int i)
{
	DlinkList p=GetElem(DL,i-1);
	if(NULL==p)
	{
		return false;
	}
	DlinkList q;
	q=p->next;
	if(q==NULL)//删除的元素不存在
		return false;
	p->next=q->next;//断链

// 下面注意要进行判断
	if(q->next!=NULL)
	{
		q->next->prior=p;
	}
	free(q);//释放对应结点的空间
	return true;
}
//链表打印
void PrintDList(DlinkList DL)
{
	DL=DL->next;
	while(DL!=NULL)
	{
		printf("%3d",DL->data);
		DL=DL->next;
	}
	printf("n");
}

 
//2.3.3 双链表增删查
int main()
{
	DlinkList DL;
	DlinkList search;
	Dlist_head_insert(DL);
	//Dlist_tail_insert(DL);
	//3 4 5 6 7 9999
	PrintDList(DL);
	search=GetElem(DL,2);
	if(search!=NULL)
	{
		printf("按序号查找成功n");
		printf("%dn",search->data);
	}
	DListFrontInsert(DL,3,99);
	PrintDList(DL);
	DListDelete(DL,2);
	PrintDList(DL);
	system("pause");
}
双向链表的删除

= 删除双链表中结点*p的后继结点*q
1、p->next=q->next ;
2、q->next-> prior=p;
3、free(q) ;

第五次 直播 其他链表 循环单链表
  • 循环单链表与单链表的区别在于,表中最后一个结点的next指针不是NULL,而是指向头结点L,从而整个链表形成一个环

静态链表
  • 静态链表是借助数组来描述线性表的链式存储结构,结构类型如下
#define Maxsize 50
typedef struct { 
ElemType data ;
int next ;
) Slinklist[Maxsize] ;

常见问题
  • 在链表中插入第 i 个位置和删除第 i 个元素不需要用引用的原因在于:不需要改变头节点
第六次 直播 引用解析、栈与队列

为什么我们需要在形参的地方使用引用?

  • 在子函数中去给对应的形参赋值后,子函数结束,主函数中对应的实参就发生了变化,如果没有使用引用,那么在子函数中给形参赋值后,子函数结束,主函数中对应的实参不会变化的
栈的实现

  • 入栈:Top 栈顶指针先加加 ; 出栈:Top 栈顶指针后减减
栈的基本 *** 作
#include 
#include 

#define MaxSize 50
typedef int ElemType;
typedef struct {
	ElemType data[MaxSize];//数组
	int top;
}SqStack;

void InitStack(SqStack &S)
{
	S.top = -1;//代表栈为空
}

bool StackEmpty(SqStack S)
{
	if (-1 == S.top)
	{
		return true;
	}
	return false;
}
bool Push(SqStack& S, ElemType x)
{
	if (S.top == MaxSize - 1)
	{
		return false;//栈满了
	}
	S.data[++S.top] = x;
	return true;//返回true就是入栈成功
}
//获取栈顶元素
bool GetTop(SqStack S, ElemType &x)
{
	if (StackEmpty(S))//栈为空
	{
		return false;
	}
	x = S.data[S.top];
	return true;
}
bool Pop(SqStack& S, ElemType& x)
{
	if (StackEmpty(S))//栈为空
	{
		return false;
	}
	x = S.data[S.top--];//等价于x = S.data[S.top];再做	S.top--;
	return true;
}
int main()
{
	SqStack S;
	bool flag;
	ElemType m;//存储拿出来的栈顶元素的
	InitStack(S);//初始化
	flag = StackEmpty(S);
	if (flag)
	{
		printf("栈是空的n");
	}
	Push(S, 3);//入栈元素3
	Push(S, 4);//入栈元素4
	Push(S, 5);
	flag = GetTop(S, m);//获取栈顶元素,但是S.top值不变
	if (flag)
	{
		printf("获取栈顶元素为 %dn", m);
	}
	flag = Pop(S, m);//d出栈顶元素
	if (flag)
	{
		printf("d出元素为 %dn", m);
	}
	return 0;
}

拓展知识: 链表实现的栈是头部插入与头部删除

队列

循环队列

循环队列图示

为了区分队空还是队满的情况:

1、以牺牲一个单元区分队空和队满
2、类型中增设表示数据元素个数的数据单元
3、类型中增设tag 数据成员

入队

出队

队列全局代码

#include 
#include 

#define MaxSize 5
typedef int ElemType;
typedef struct{
	ElemType data[MaxSize];//数组,存储MaxSize-1个元素
	int front,rear;//队列头 队列尾
}SqQueue;

void InitQueue(SqQueue &Q)
{
	Q.rear=Q.front=0;
}
//判空
bool isEmpty(SqQueue &Q)
{
	if(Q.rear==Q.front)//不需要为零
		return true;
	else
		return false;
}
//入队
bool EnQueue(SqQueue &Q,ElemType x)
{
	if((Q.rear+1)%MaxSize==Q.front) //判断是否队满
		return false;
	Q.data[Q.rear]=x;//3 4 5 6
	Q.rear=(Q.rear+1)%MaxSize;
	return true;
}
//出队
bool DeQueue(SqQueue &Q,ElemType &x)
{
	if(Q.rear==Q.front)
		return false;
	x=Q.data[Q.front];//先进先出
	Q.front=(Q.front+1)%MaxSize;
	return true;
}
//《王道C督学营》课程
//王道数据结构 3.2 循环队列
int main()
{
	SqQueue Q;
	bool ret;//存储返回值
	ElemType element;//存储出队元素
	InitQueue(Q);
	ret=isEmpty(Q);
	if(ret)
	{
		printf("队列为空n");
	}else{
		printf("队列不为空n");
	}
	EnQueue(Q,3);
	EnQueue(Q,4);
	EnQueue(Q,5);
	ret=EnQueue(Q,6);
	ret=EnQueue(Q,7);
	if(ret)
	{
		printf("入队成功n");
	}else{
		printf("入队失败n");
	}
	ret=DeQueue(Q,element);
	if(ret)
	{
		printf("出队成功,元素值为 %dn",element);
	}else{
		printf("出队失败n");
	}
	ret=DeQueue(Q,element);
	if(ret)
	{
		printf("出队成功,元素值为 %dn",element);
	}else{
		printf("出队失败n");
	}
	ret=EnQueue(Q,8);
	if(ret)
	{
		printf("入队成功n");
	}else{
		printf("入队失败n");
	}
	system("pause");
}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5115025.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-17
下一篇 2022-11-17

发表评论

登录后才能评论

评论列表(0条)

保存