双向链表
概念
由于单向链表只能通过指针单向的访问后继节点,不能向前遍历前驱节点,所以要引入双向链表。
双向链表:在保持单向链表的基础上,既可以向后遍历后继节点,也可以向前遍历前驱节点。 双向链表的组成
头节点结构体格式:
struct head
{
int len; //头节点的数据域
struct node *next;
}
普通节点结构体格式:
struct node
{
int data; //普通节点的数据域
struct node *next;
}
双向链表节点的结构体格式
typedef int DataType;
typedef struct node
{
union
{
int len; //头节点的数据域
DataType data; //普通节点的数据域
};
struct node *next; //指向下一个节点的指针
struct node *prior; //指向前一个节点的指针
}doubleLink,*doubleLinkPtr;
双向链表的相关操作(功能函数的封装)
创建
函数返回值:节点指针类型
注意判断申请的空间是否合法
申请成功,需要将数据域置0,指针域置NULL
判空
参数列表:头指针
注意判断申请的空间是否合法
申请节点,封装数据
参数列表:插入数据
注意判断申请的空间是否合法
头插
参数列表:头指针,插入数据
注意判断申请的空间是否合法
遍历
参数列表:头指针
注意判断申请的空间是否合法
任意位置插入
参数列表:头指针,插入位置,插入数据
注意判断申请的空间是否合法
任意位置删除
参数列表:头指针,删除位置
注意判断申请的空间是否合法
销毁
参数列表:头指针
注意判断申请的空间是否合法
单向循环链表
循环概念
首尾相连的链表,可以通过任意应该节点,去遍历任意一个节点
种类:单向循环,双向循环
单向循环链表节点原型
typedef int DataType;
typedef struct node
{
union
{
int len; //头结点数据域
DataType data; //普通节点数据域
};
struct node *next;
}cyclicLink, *cyclicLinkPtr;
单向循环链表的相关操作(功能函数的封装)
创建
函数返回值:节点指针类型
注意判断申请的空间是否合法
申请成功,需要将数据域置0,指针域的指针指向自己
判空
参数列表:头指针
注意判断申请的空间是否合法
尾插
参数列表:头指针,插入数据
注意判断申请的空间是否合法
尾删
参数列表:头指针
注意判断申请的空间是否合法
遍历
参数列表:头指针
注意判断申请的空间是否合法
销毁
参数列表:头指针
注意判断申请的空间是否合法
栈
栈的概念:操作受限的线性表,插入和删除只能在一段操作
栈的特点:先进后出(FILO),后进先出(LIFO)
栈顶:可以增加或删除数据的一段
栈底:不可以增加或删除数据的一段
栈的种类:顺序栈,链式栈
顺序栈
概念
顺序存储的栈(保证数据要逻辑相连,物理内存上也要相连,还要满足栈的特点)
顺序栈的组成
需要一片连续的空间存放数据。(可以是数组,可以是堆区的连续空间)
需要一个变量记录栈顶元素的下标
顺序栈的结构体原型
//宏定义 栈的最大容量
#define MAX 30
//类型重定义
typedef int DataType
typedef struct stack
{
DataType *data; //
int top; //记录栈顶下标
}stack,*stackPtr;
顺序栈的相关操作(功能函数的封装)
创建
函数返回值:顺序栈的指针
参数列表:顺序栈
判断申请空间是否合法
判空
参数列表:顺序栈
判断申请空间是否合法
判满
参数列表:顺序栈
判断申请空间是否合法
入栈
参数列表:顺序栈,入栈的数据
判断申请空间是否合法,判满
遍历
参数列表:顺序栈
判断申请空间是否合法
出栈
参数列表:顺序栈
判断申请空间是否合法
获取栈顶元素
参数列表:
判断申请空间是否合法
栈的大小
参数列表:顺序栈
判断申请空间是否合法
销毁
参数列表:顺序栈
判断申请空间是否合法
练习
双向循环链表
创建,判空,尾插,遍历,尾删,销毁
头文件
#ifndef __DOUBLECYCLICLINK_H__
#define __DOUBLECYCLICLINK_H__
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef int DataType;
typedef struct node
{
union
{
int len; //头结点数据域
DataType data; //普通节点数据域
};
struct node *next;
struct node *prior;
}doubleCyclicLink, *doubleCyclicLinkPtr;
//创建
doubleCyclicLinkPtr create();
//判空
int empty(doubleCyclicLinkPtr l);
//尾插
void insert(doubleCyclicLinkPtr l,int a);
//遍历
void show(doubleCyclicLinkPtr l);
//尾删
void my_delete(doubleCyclicLinkPtr l);
//销毁
void my_free(doubleCyclicLinkPtr l);
#endif
源文件
#include "doubleCyclicLink.h"
//创建
doubleCyclicLinkPtr create()
{
doubleCyclicLinkPtr l=(doubleCyclicLinkPtr)malloc(sizeof(doubleCyclicLink));
if(NULL==l)
{
printf("创建失败\n");
return NULL;
}
l->len=0;
l->next=NULL;
l->prior=NULL;
printf("创建成功\n");
return l;
}
//判空
int empty(doubleCyclicLinkPtr l)
{
if(NULL==l)
{
printf("判空失败\n");
return -1;
}
return l->len==0;
}
//尾插
void insert(doubleCyclicLinkPtr l,int a)
{
if(NULL==l)
{
printf("插入失败\n");
return;
}
//申请空间,封装数据
doubleCyclicLinkPtr p=(doubleCyclicLinkPtr)malloc(sizeof(doubleCyclicLink));
if(NULL==p)
{
printf("申请失败\n");
return;
}
p->data=a;
p->next=NULL;
p->prior=NULL;
doubleCyclicLinkPtr q=l;
for(int i=0;i<l->len;i++)
{
q=q->next;
}
q->next=p;
p->next=l;
q->prior=p;
p->prior=l;
l->len++;
}
//遍历
void show(doubleCyclicLinkPtr l)
{
if(NULL==l)
{
printf("遍历失败\n");
return;
}
doubleCyclicLinkPtr p=l;
for(int i=0;i<l->len;i++)
{
p=p->next;
printf("%d ",p->data);
}
putchar(10);
}
//尾删
void my_delete(doubleCyclicLinkPtr l)
{
if(NULL==l)
{
printf("遍历失败\n");
return;
}
doubleCyclicLinkPtr p=l;
for(int i=0;i<l->len-1;i++)
{
p=p->next;
}
free(p->next);
p->next=l;
l->len--;
}
//销毁
void my_free(doubleCyclicLinkPtr l)
{
if(NULL==l)
{
printf("遍历失败\n");
return;
}
while(l->next!=l)
{
my_delete(l);
}
free(l);
l=NULL;
printf("销毁成功\n");
}
main文件
#include "doubleCyclicLink.h"
int main()
{
doubleCyclicLinkPtr l=create();
insert(l,1);
insert(l,2);
insert(l,3);
insert(l,4);
insert(l,5);
show(l);
my_delete(l);
show(l);
my_free(l);
}