一、Xmind整理:
二、课上练习:
练习1:个栈的入栈次序ABCDE,则栈的不可能的输出序列是(D)
A.ABCDE B.DECBA C.EDCBA D.DCEAB
栈的特点是先进后出,后进先出,D不符合该思想,根据题意,可以推测D选项首先入栈的是ABCD,然后D出,C出,E进入,E出,但在这种情况下,B应当比A先出栈。
练习2:顺序栈
练习3:顺序栈的结构体定义
练习4:顺序栈的插入
/*
* function: 入栈
* @param [ in]
* @param [out]
* @return 成功返回0 失败返回-1
*/
int list_stack_push(datatype e,StackList *stack)
{
//1.判断栈是否创建
//2.判断栈是否为满
if(NULL==stack || stack->top==MAXSIZE-1)
{
puts("push stack error");
return -1;
}
//3.入栈:先加后压
//stack->top++;
stack->data[++stack->top]=e;
return 0;
}
练习5:顺序栈的删除
/*
* function: 出栈
* @param [ in]
* @param [out]
* @return 成功返回0 失败返回-1
*/
int list_stack_pop(StackList *stack)
{
//1.判断栈是否创建
//2.判断栈是否为空
if(NULL==stack || stack->top==-1)
{
puts("pop error");
return -1;
}
//3.出栈:先弹后减
printf("pop data is:%d\n",stack->data[stack->top--]);
// stack->top--;
return 0;
}
练习6:顺序栈的遍历
/*
* function: 顺序栈的输出
* @param [ in]
* @param [out]
* @return 无
*/
void stack_output(StackList *stack)
{
//1.判断栈是否创建
//2.判断栈是否为空
if(NULL==stack || stack->top==-1)
{
puts("output error");
return;
}
//3.输出
for(int i=0;i<=stack->top;i++)
{
printf("%d\t",stack->data[i]);
}
puts("");
}
练习7:顺序栈的创建
/*
* function: 创建栈
* @param [ in]
* @param [out]
* @return
*/
StackList *create_stack()
{
StackList *stack=(StackList *)malloc(sizeof(StackList));
if(NULL == stack)
{
return NULL;
}
//栈顶置空
stack->top=-1;
memset(stack->data,0,sizeof(stack->data));
return stack;
}
练习8:链栈
练习9:链栈节点创建【单链表节点创建】
/*
* function: 创建一个节点
* @param [ in]
* @param [out]
* @return
*/
LinkStack create_node()
{
LinkStack node=(LinkStack)malloc(sizeof(struct Node));
if(NULL==node)
return NULL;
node->data=0;
node->next=NULL;
return node;//0x10
}
练习10:链栈插入【单链表头插】
/*
* function: 链栈的入站
* @param [ in]
* @param [out]
* @return
*/
LinkStack link_stack_push(datatype e,LinkStack top)
{
//在堆区创建一个节点
LinkStack node=create_node();//在堆区申请一个节点
node->data=e;//数据域赋值为e
//node节点链接到链表中
node->next=top;
top=node;
return top;//因为自定义函数指针的改变不影响实参,需要返回
}
练习11:链栈删除【单链表头删】
/*
* function: 头删除
* @param [ in]
* @param [out]
* @return
*/
LinkStack link_stack_pop(LinkStack top)
{
//判断链表是否为空
if(NULL==top)
{
return top;
}
if(top->next==NULL)
{
free(L);
L=NULL;
}
else
{
LinkStack q=top->next;
top->data=q->data;
top->next=q->next;
free(q);
q=NULL;
}
return top;
}
练习12:链栈遍历【单链表遍历】
/*
* function: 循环遍历
* @param [ in]
* @param [out]
* @return 成功返回0 失败返回-1
*/
int link_output(LinkStack top)
{
//判断是否创建
//判断是否为空
if(NULL==top )
{
return -1;
}
while(top!=NULL)
{
printf("%d\t",top->data);
top=top->next;
}
puts("");
}
栈的整体代码:
stack_head.h:
#ifndef __STACK_HEAD_H__
#define __STACK_HEAD_H__
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXSIZE 4
typedef int datatype;
typedef struct
{
//栈顶
int top;
//数据元素
datatype data[MAXSIZE];
}StackList;
int list_stack_pop(StackList *stack);
StackList *create_stack();
int list_stack_push(datatype e,StackList *stack);
void stack_output(StackList *stack);
//定义单链表节点结构体
typedef struct Node
{
//数据域:数据元素
datatype data;
//指针域:存储下一个节点的地址
struct Node *next;
}*LinkStack;
LinkStack link_stack_push(datatype e,LinkStack top);
int link_output(LinkStack top);
LinkStack link_stack_pop(LinkStack L);
#endif
stack_test.c:
#include "stack_head.h"
/*
* function: 创建栈
* @param [ in]
* @param [out]
* @return
*/
StackList *create_stack()
{
StackList *stack=(StackList *)malloc(sizeof(StackList));
if(NULL == stack)
{
return NULL;
}
//栈顶置空
stack->top=-1;
memset(stack->data,0,sizeof(stack->data));
return stack;
}
/*
* function: 入栈
* @param [ in]
* @param [out]
* @return 成功返回0 失败返回-1
*/
int list_stack_push(datatype e,StackList *stack)
{
//1.判断栈是否创建
//2.判断栈是否为满
if(NULL==stack || stack->top==MAXSIZE-1)
{
puts("push stack error");
return -1;
}
//3.入栈:先加后压
//stack->top++;
stack->data[++stack->top]=e;
return 0;
}
/*
* function: 顺序栈的输出
* @param [ in]
* @param [out]
* @return 无
*/
void stack_output(StackList *stack)
{
//1.判断栈是否创建
//2.判断栈是否为空
if(NULL==stack || stack->top==-1)
{
puts("output error");
return;
}
//3.输出
for(int i=0;i<=stack->top;i++)
{
printf("%d\t",stack->data[i]);
}
puts("");
}
/*
* function: 出栈
* @param [ in]
* @param [out]
* @return 成功返回0 失败返回-1
*/
int list_stack_pop(StackList *stack)
{
//1.判断栈是否创建
//2.判断栈是否为空
if(NULL==stack || stack->top==-1)
{
puts("pop error");
return -1;
}
//3.出栈:先弹后减
printf("pop data is:%d\n",stack->data[stack->top--]);
// stack->top--;
return 0;
}
/*
* function: 创建一个节点
* @param [ in]
* @param [out]
* @return
*/
LinkStack create_node()
{
LinkStack node=(LinkStack)malloc(sizeof(struct Node));
if(NULL==node)
return NULL;
node->data=0;
node->next=NULL;
return node;//0x10
}/*
* function: 链栈的入站
* @param [ in]
* @param [out]
* @return
*/
LinkStack link_stack_push(datatype e,LinkStack top)
{
//在堆区创建一个节点
LinkStack node=create_node();//在堆区申请一个节点
node->data=e;//数据域赋值为e
//node节点链接到链表中
node->next=top;
top=node;
return top;//因为自定义函数指针的改变不影响实参,需要返回
}
/*
* function: 循环遍历
* @param [ in]
* @param [out]
* @return 成功返回0 失败返回-1
*/
int link_output(LinkStack top)
{
//判断是否创建
//判断是否为空
if(NULL==top )
{
return -1;
}
while(top!=NULL)
{
printf("%d\t",top->data);
top=top->next;
}
puts("");
}
/*
* function: 头删除
* @param [ in]
* @param [out]
* @return
*/
LinkStack link_stack_pop(LinkStack top)
{
//判断链表是否为空
if(NULL==top)
{
return top;
}
if(top->next==NULL)
{
free(L);
L=NULL;
}
else
{
LinkStack q=top->next;
top->data=q->data;
top->next=q->next;
free(q);
q=NULL;
}
return top;
}
stack_main.c:
#include "stack_head.h"
int main(int argc, const char *argv[])
{
/*
StackList *stack=create_stack();
char continu;
datatype e;
int flag;
do
{
//入栈
printf("please enter e:");
scanf("%d",&e);
flag=list_stack_push(e,stack);
if(flag==-1)
break;
printf("Please enter whether you will continue");
scanf(" %c",&continu);
}while(continu!='N'&&continu!='n');
stack_output(stack);
do
{
flag=list_stack_pop(stack);
if(flag==-1)
break;
printf("Please enter whether you will continue");
scanf(" %c",&continu);
}while(continu!='N'&&continu!='n');
stack_output(stack);
*/
LinkStack top=NULL;
char continu;
datatype e;
int flag;
do
{
//入栈
printf("please enter e:");
scanf("%d",&e);
top=link_stack_push(e,top);
printf("Please enter whether you will continue");
scanf(" %c",&continu);
}while(continu!='N'&&continu!='n');
link_output(top);
do
{
top=link_stack_pop(top);
printf("Please enter whether you will continue");
scanf(" %c",&continu);
}while(continu!='N'&&continu!='n');
link_output(top);
return 0;
}
练习13:顺序队列
练习14:顺序队列创建
/*
* function: 在堆区申请空间
* @param [ in]
* @param [out]
* @return 返回地址
*/
QueueList *create_queue()
{
QueueList *queue=(QueueList *)malloc(sizeof(QueueList));
if(NULL==queue)
return NULL;
queue->front=queue->rear=0;
memset(queue->data,0,sizeof(queue->data));
return queue;
}
练习15:顺序队列入队
/*
* function: 入队
* @param [ in]
* @param [out]
* @return 成功返回0 失败返回-1
*/
int enqueue(datatype e,QueueList *queue)
{
//1.判断是否创建
//2.判断是否满
if(NULL==queue || queue->rear==MAXSIZE)
{
puts("enqueue error");
return -1;
}
//3.入队:在队尾插入
queue->data[queue->rear++]=e;
// queue->rear++;
return 0;
}
练习16:顺序队列出队
/*
* function: 出队
* @param [ in]
* @param [out]
* @return 成功返回0 失败返回-1
*/
int delqueue(QueueList *queue)
{
//1.判断是否创建
//2.判断是否为空
if(NULL==queue || queue->front==queue->rear)
{
puts("delqueue error");
return -1;
}
//3.出队:出队在队头
printf("delqueue data is:%d\n",queue->data[queue->front++]);
// queue->front++;
}
练习17:顺序队列遍历
/*
* function: 循环输出队列
* @param [ in]
* @param [out]
* @return 无
*/
void output(QueueList *queue)
{
//1.判断是否创建
//2.判断是否为空
if(NULL==queue || queue->front==queue->rear)
{
puts("output error");
return;
}
//3.从队头到队尾输出
for(int i=queue->front;i<queue->rear;i++)
{
printf("%d\t",queue->data[i]);
}
puts("");
}
练习18:循环队列
练习19:循环队列入队
/*
* function: 循环队列入队
* @param [ in]
* @param [out]
* @return 成功返回0 失败返回-1
*/
int enqueue(datatype e,QueueList *queue)
{
//1.判断是否创建
//2.判断是否满
if(NULL==queue ||queue->front==(queue->rear+1)%MAXSIZE)
{
puts("enqueue error");
return -1;
}
//3.入队:在队尾插入
queue->data[queue->rear]=e;
queue->rear=(queue->rear+1)%MAXSIZE;
return 0;
}
练习20:循环队列出队
/*
* function: 出队
* @param [ in]
* @param [out]
* @return 成功返回0 失败返回-1
*/
int delqueue(QueueList *queue)
{
//1.判断是否创建
//2.判断是否为空
if(NULL==queue || queue->front==queue->rear)
{
puts("delqueue error");
return -1;
}
//3.出队:出队在队头
printf("delqueue data is:%d\n",queue->data[queue->front]);
queue->front=(queue->front+1)%MAXSIZE;
return 0;
}
练习21:循环队列的遍历
/*
* function: 循环输出队列
* @param [ in]
* @param [out]
* @return 无
*/
void output(QueueList *queue)
{
//1.判断是否创建
//2.判断是否为空
if(NULL==queue || queue->front==queue->rear)
{
puts("output error");
return;
}
//3.从队头到队尾输出
for(int i=queue->front;i!=queue->rear;i=(i+1)%MAXSIZE)
{
printf("%d\t",queue->data[i]);
}
puts("");
}
练习22:循环队列个数计算
/*
* function: 计算循环队列个数
* @param [ in]
* @param [out]
* @return
*/
int loop_queue_count(QueueList *queue)
{
return (MAXSIZE-queue->front+queue->rear)%MAXSIZE;
}
练习23:链式队列
练习24:链式队列节点创建【单链表节点创建】
//创建节点
queue *CreateLink()
{
//创建队列:头节点,尾节点【指向单向链表的头以及尾】
queue *q=(queue *)malloc(sizeof(queue));
if(q==NULL)
return NULL;
//创建单向链表的头节点
Node *L=(Node *)malloc(sizeof(Node));
if(L==NULL)
return NULL;
L->len=0;//对单向链表头结点的数据域赋值,链表为空
L->next=NULL;//单向链表头结点没有后继节点
q->front=L;//队头指向单向链表的第一个节点
q->rear=L;//队尾指针指向单向链表的最后一个节点
return q;
}
练习25:链式队列入队【单链表尾插】
void EnqueueLink(queue *q,datatype e)
{
//1.判断队列是否创建成功
if(q==NULL)
return;
//2.入队
Node *p=(Node *)malloc(sizeof(Node));
if(p==NULL)
return;
p->data=e;
p->next=NULL;
//3.入队
q->rear->next=p;
q->rear=p;
q->front->len++;
}
练习26:链式队列出队【单链表头删】
//链式队列的出队
//成功返回出队的数据,
int dequeueLink(queue *q)
{
//1.判断队列是否存在
//2.判断队列是否为空
if(q==NULL || q->front->next==NULL)
return -1;
//3.出队
Node *p=q->front->next;
int data=p->data;
q->front->next=p->next;
free(p);
p=NULL;
q->front->len--;
return data;
}
练习27:链式队列遍历【单链表的输出】
//链是队列的遍历
void LinkShow(queue *q)
{
printf("\n");
Node *p=q->front;
while(p->next)
{
p=p->next;
printf("%d\t",p->data);
}
printf("\n");
}
练习28:释放空间
//释放头节点后面的节点
int t=q->front->len;
for(int i=0;i<t;i++)
{
dequeueLink(q);
}
free(q->front);//删除头节点
free(q);//释放队列的空间
q=NULL;//q释放没有指向,防止野指针
练习29:直接插入排序
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
int m,t,j;
int arr[100];
printf("请问你要插入几个数:");
scanf("%d",&m);
for(int i=0;i<m;i++)
{
printf("请输入第%d个数:",i+1);
scanf("%d",&arr[i]);
}
int *p=arr;
for(int i=1;i<m;i++)
{
t=*(p+i);
for(j=i-1;j>=0;j--)
{
if(t<*(p+j))
{
*(p+j+1)=*(p+j);
}
else
break;
}
*(p+j+1)=t;
}
for(int i=0;i<m;i++)
printf("%d\t",*(p+i));
puts("");
return 0;
}
三、课后作业:
实现双向链表的逆置
方法一:
DoubleLink rev_doublelink(DoubleLink L)
{
//判断链表是否为空
if(NULL==L)
return L;
//判断链表只有一个节点
if(NULL == L || L->next==NULL)
{
return L;
}
//先找最后一个节点的位置
DoubleLink p=L;
while(p->next!=NULL)
{
p=p->next;
}
DoubleLink q=L;
DoubleLink s=NULL;
while(q!=NULL)
{
s=q->next;
q->next=q->prev;
q->prev=s;
q=s;
}
return p;
}
方法二:
DoubleLink rev_doublelink(DoubleLink L)
{
//判断链表是否为空
if(NULL==L)
return L;
//判断链表只有一个节点
if(NULL == L || L->next==NULL)
{
return L;
}
DoubleLink p=L;
DoubleLink q=NULL;
while (p!=NULL)
{
q=p->prev;
p->prev=p->next;
p->next=q;
p=p->prev;
}
// 更新头节点的prev指针为NULL
if(q!=NULL)
{
L=q->prev;
L->prev=NULL;
}
return L;
}