目录
链式栈
头文件:
#ifndef __LINKSTACK_H__
#define __LINKSTACK_H__
typedef int datatype;
typedef struct Node
{
union
{
datatype data;
int len;
};
struct Node *next;
}LinkStack,*LinkStackPtr;
//创建链式栈
LinkStackPtr stack_create();
//判空
int stack_empty(LinkStackPtr L);
//入栈,头插的方式
int stack_push(LinkStackPtr L,datatype e);
//遍历
void stack_show(LinkStackPtr L);
//出栈,头删的方式
int stack_pop(LinkStackPtr L);
//销毁
void stack_free(LinkStackPtr L);
#endif
源文件:
#include"linkstack.h"
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//创建链式栈
LinkStackPtr stack_create(){
LinkStackPtr L = (LinkStackPtr)malloc(sizeof(LinkStack));
if(NULL==L){
printf("创建失败\n");
return NULL;
}
//创建成功后,初始化
L->len = 0;
L->next = NULL;
printf("创建成功\n");
return L;
}
//判空
int stack_empty(LinkStackPtr L){
//判断条件
if(NULL==L){
printf("所给链表不合法\n");
return -1;
}
//如果头结点的next为NULL,说明链表为空
return L->next == NULL;
}
//入栈,头插的方式
int stack_push(LinkStackPtr L,datatype e){
if(NULL==L){
printf("所给链表不合法\n");
return -1;
}
//如果链表合法,将要添加的数据封装进一个节点然后链接
LinkStackPtr p = (LinkStackPtr)malloc(sizeof(LinkStack));
if(NULL==p){
printf("节点创建失败\n");
return 0;
}
p->data = e;
p->next = NULL;
//头插操作
p->next = L->next;
L->next = p;
//链表长度的变化
L->len++;
printf("%d插入成功\n",L->next->data);
return 1;
}
//遍历
void stack_show(LinkStackPtr L){
if(NULL==L|| stack_empty(L)){
printf("输出失败\n");
return;
}
//如果链表合法,从栈顶到栈底输出
LinkStackPtr p = L->next;
while(NULL!=p){
printf("%d\t",p->data);
p = p->next;
}
putchar(10);
return;
}
//出栈,头删的方式
int stack_pop(LinkStackPtr L){
if(NULL==L|| stack_empty(L)){
printf("出栈失败\n");
return -1;
}
//头删操作
LinkStackPtr p = L->next; //标记
printf("%d出栈成功\n",p->data);
L->next = p->next;//孤立
//释放
free(p);
L->len--;
//链表长度的变化
return 1;
}
//销毁
void stack_free(LinkStackPtr L){
if(NULL==L|| stack_empty(L)){
printf("销毁失败\n");
return;
}
//将所有非头节点出栈
while(L->next!=NULL){
stack_pop(L);
}
//释放头结点
free(L);
L = NULL;
printf("释放成功\n");
return;
}
测试文件:
#include"linkstack.h"
#include<stdio.h>
int main(int argc, const char *argv[])
{
LinkStackPtr L = stack_create();
if(NULL==L){
return -1;
}
//调用入栈函数
stack_push(L,6);
stack_push(L,9);
stack_push(L,3);
stack_push(L,4);
stack_push(L,7);
stack_push(L,5);
stack_push(L,1);
//调用遍历函数
stack_show(L);
//调用出栈函数
stack_pop(L);
stack_pop(L);
stack_pop(L);
printf("开始销毁\n");
//销毁
stack_free(L);
L = NULL;
return 0;
}
结果:
链式队列
头文件:
#ifndef __LINKQUEUE_H__
#define __LINKQUEUE_H__
typedef int datatype;
//定义节点类型
typedef struct Node
{
union
{
datatype data;
int len;
};
struct Node *next;
}Node;
//定义链式队列
typedef struct
{
Node *Head;
Node *Tail;
}LinkQueue,*LinkQueuePtr;
//创建链式队列
LinkQueuePtr list_create();
//判空
int list_empty(LinkQueuePtr LQ);
//创建节点
Node *linklist_create(datatype e);
//入队,采用尾插方式
int list_push(LinkQueuePtr LQ,datatype e);
//出队,采用头删方式
int list_pop(LinkQueuePtr LQ);
//按顺序展示队列元素
void list_show(LinkQueuePtr LQ);
//销毁队伍
void list_free(LinkQueuePtr LQ);
#endif
源文件:
#include"linkqueue.h"
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//创建链式队列
LinkQueuePtr list_create(){
//创建一个链式队列的结构体,并在堆区申请空间
LinkQueuePtr LQ = (LinkQueuePtr)malloc(sizeof(LinkQueue));
if(NULL==LQ){
printf("队列创建失败\n");
return NULL;
}
//创建成功的话,说明里面有两个指针
//LQ->Head,LQ->Tail是野指针
//创建头结点并在堆区申请空间
Node *L = (Node *)malloc(sizeof(Node));
if(NULL==L){
printf("头结点创建失败\n");
return NULL;
}
//如果成功需要对链表进行初始化
//头结点的初始化
L->len = 0;
L->next = NULL;
//链式队列的初始化
LQ->Head = L;
LQ->Tail = L;
printf("队列创建成功\n");
return LQ;
}
//判空
int list_empty(LinkQueuePtr LQ){
//判断逻辑
if(NULL==LQ|| NULL==LQ->Head){
printf("所给队列不合法\n");
return 0;
}
return LQ->Head==LQ->Tail;
}
//创建节点
Node *linklist_create(datatype e){
//申请一个节点
Node *p = (Node *)malloc(sizeof(Node));
if(NULL==p){
printf("入队失败\n");
return NULL;
}
//存入要存储的数据
p->data = e;
p->next = NULL;
return p;
}
//入队,采用尾插方式
int list_push(LinkQueuePtr LQ,datatype e){
//判断逻辑
if(NULL==LQ){
printf("所给队列不合法\n");
return 0;
}
//创建一个保存有e的节点,申请节点封装数据
Node *p = linklist_create(e);
//将新节点连接到队尾指针指向的节点后面
LQ->Tail->next = p; //尾插,让链表中原来的最后一个节点指向要插入的节点
LQ->Tail = p;//新的p变成了新的尾,所以要让队列的尾指针指向它
LQ->Head->len++;//链表长度的变化
printf("%d入队成功\n",e);
return 1;
}
//出队,采用头删方式
int list_pop(LinkQueuePtr LQ){
if(NULL==LQ|| list_empty(LQ)){
printf("出队失败\n");
return -1;
}
printf("%d出队成功\n",LQ->Head->next->data);
//如果删除的是链表中除了头结点外的最后一个节点,要让LQ->Tail指向头结点
//表示队列已经空了
if(LQ->Head->next==LQ->Tail){
LQ->Tail = LQ->Head;
}
//头删操作
Node *p = LQ->Head->next; //标记
LQ->Head->next = p->next; //孤立
free(p);
p = NULL; //释放
//链表长度的变化
LQ->Head->len--;
//判断队伍是否已经删除完所有节点
/*
if(LQ->Head->next == NULL){
//将尾指针重新指向头结点
LQ->Tail = LQ->Head;
}
*/
return 1;
}
//按顺序展示队列元素
void list_show(LinkQueuePtr LQ){
if(NULL==LQ|| list_empty(LQ)){
printf("展示失败\n");
return ;
}
//从头结点的下一个节点开始遍历输出
//定义一个遍历指针,初始指向第一个元素所在的节点,即头结点的下一个节点,
Node *p = LQ->Head->next;
while(NULL!=p){
printf("%d\t",p->data);
p = p->next;
}
putchar(10);
return;
}
//释放
void list_free(LinkQueuePtr LQ){
if(NULL==LQ){
printf("释放失败\n");
return;
}
//释放整个链表
while(!list_empty(LQ)){
list_pop(LQ);
}
//释放头结点
//循环出列结束后,此时队列为空,头指针和尾指针都指向头结点
free(LQ->Head);
LQ->Head = NULL;
LQ->Tail = NULL;
//头结点也释放结束,只需再将队列释放即可
free(LQ);
LQ = NULL;
printf("释放成功\n");
return;
}
测试文件:
#include"linkqueue.h"
#include<stdio.h>
int main(int argc, const char *argv[])
{
LinkQueuePtr LQ = list_create();
if(NULL==LQ){
return -1;
}
//调用入队函数
list_push(LQ,1);
list_push(LQ,2);
list_push(LQ,3);
list_push(LQ,4);
list_push(LQ,5);
list_push(LQ,6);
list_push(LQ,7);
list_push(LQ,8);
list_push(LQ,9);
list_push(LQ,10);
//调用出队函数
list_pop(LQ);
list_pop(LQ);
//调用遍历函数
list_show(LQ);
//调用释放函数
list_free(LQ);
LQ = NULL;
return 0;
}
结果:
思维导图