文章目录
下面写的代码可能感觉会很乱,所以加上了目录,意在为了引导,也就是你需要回顾哪个算法,就能够快速定位到该位置,如果从上往下去找的话,估计脑壳也疼死了。
一、线性表的基本操作
(一)顺序表的基本操作
1. 顺序表的结构体
#define MAX_SIZE 30 //设置顺序表最大容量
typedef struct
{
int data[MAX_SIZE]; //设置数据最大长度
int length; //设置数据当前长度
}Sqlist;
2. 顺序表的查找
/*
method:
顺序表的查找
param:
L 顺序表
n代表要查找的元素
*/
int Find_Elem(Sqlist L, int n)
{
int result = 0; //存放所查找到匹配值的下标
for (result; result < n; result++)
{
if (L.data[result] == n)
return result;
}
return ERROR;
}
3. 顺序表的插入
/*
method:
顺序表的插入
param:
sqlist 要操作的顺序表
pos 要插入的位置
data 要插入的数据
*/
int Insert_Elem(Sqlist* sqlist, int pos, int data)
{
int i = 0;
if (pos<0 || pos>sqlist->length || sqlist->length == MAX_SIZE) //这里是判断 如果 查询位置不在线性表内,或者线性表长度满了,则返回Error
return ERROR;
for (i = sqlist->length-1; i >= pos; i--) //这个循环将pos位置后面的元素由后往前向后挪1个位置
sqlist->data[i+1] = sqlist->data[i];
sqlist->data[pos] = data; //插入设定值
sqlist->length += 1; //线性表长度加1
return OK;
}
4. 顺序表的删除
/*
method:
顺序表的删除
param:
sqlist 要操作的顺序表
pos 要删除的位置
num 存放删除的元素
*/
int Delete_Elem(Sqlist* sqlist, int pos,int *num)
{
int i = pos;
if (pos<0 || pos >sqlist->length)
return ERROR;
*num = sqlist->data[pos]; //得到删除的值
for (i; i < sqlist->length; i++) //由前往后,pos位置后面的值依次往前移动
sqlist->data[i] = sqlist->data[i + 1];
sqlist->length -= 1; //线性表长度减1
return OK;
}
5. 顺序表的更改
/*
method:
顺序表的更改
param:
sqlist 要操作的顺序表
pos 要修改的位置
num 要修改的值
*/
int Alter_Elem(Sqlist* sqlist, int pos, int num)
{
if (pos<0 || pos >sqlist->length) //判断范围
return ERROR;
sqlist->data[pos] = num; //更改
return OK;
}
(二)单链表的基本操作
1. 单链表的结构体
typedef struct LNODE
{
int data; //数据域
struct LNODE* next; //指针域
}LNODE;
2. 尾插法创建单链表
/*
method:
尾插法创建单链表
param:
lnode 要操作的顺序表
dat 数组中存放要创建链表的数据
n 要创建单链表的长度
*/
int Create_Lnode_Tail(LNODE* lnode, int dat[], int n)
{
LNODE* p, * q;
int i = 0;
//lnode = (LNODE*)__vcrt_malloc_normal(sizeof(LNODE)); //创造头节点
lnode->data = NULL; //初始化头节点
lnode->next = NULL;
p = lnode;
for (i; i < n; i++)
{
q = (LNODE*)__vcrt_malloc_normal(sizeof(LNODE)); //创建新结点
q->data = dat[i]; //接收数组元素
p->next= q; //尾插法核心
p = p->next;
}
p->next = NULL; //表尾
Show_Lnode_data(lnode); //遍历单链表元素
return OK;
}
3. 头插法创建单链表
/*
method:
头插法创建单链表
param:
lnode 要操作的顺序表
dat 数组中存放要创建链表的数据
n 要创建单链表的长度
*/
int Create_Lnode_Head(LNODE* lnode, int dat[], int n)
{
int i = 0;
LNODE* q;
//lnode = (LNODE *)malloc(sizeof(LNODE)); //给lnode指针分配内存空间
lnode->data = NULL; //初始化头结点
lnode->next = NULL;
for (i; i < n; i++)
{
q = (LNODE*)malloc(sizeof(LNODE)); //创建新结点
q->data = dat[i]; //接收数组元素
q->next = lnode->next; //头插法的核心
lnode->next = q;
}
Show_Lnode_data(lnode);
return OK;
}
4. 遍历单链表
/*
method:
遍历单链表的数据
param:
lnode 要操作的顺序表
*/
void Show_Lnode_data(LNODE* lnode)
{
LNODE* p = lnode; //p指向单链表的头结点
printf("%p", lnode); //打印出来头结点指针的地址
while (p->next != NULL) //判断下一个结点是否为空
{
printf("->%d", p->next->data); //打印出来链表中的数据
p = p->next; //遍历单链表
}
printf("\n");
}
5. 合并两个单链表
/*
method:
遍历单链表的数据
param:
A 要操作的顺序表
B 要操作的顺序表
C 存放合并后的单链表
*/
void Merge_Lnode(LNODE* A, LNODE* B, LNODE** C) //这里取指针的指针
{
LNODE* a = A->next, * b =B->next, * c ;
*C = A; //将A的存储空间的地址给*C
(*C)->next = NULL;
__vcrt_free_normal(B); //释放掉B的所占的存储空间
c = *C; //指针c指向头结点C
while (a != NULL && b != NULL) //判断这两个结点大小
{
if (a->data > b->data)
{
c->next = b; //链接单链表
b = b->next; //取下一个结点
c = c->next; //始终表示最后一个结点的存储空间
}
else
{
c->next = a; //链接单链表
a = a->next; //取下一个结点
c = c->next; //始终表示最后一个结点的存储空间
}
}
if (a != NULL) c->next = a; //若链表a还有值,则直接填补到末尾
if (b != NULL) c->next = b; //若链表b还有值,则直接填补到末尾
}
(三)双链表的基本操作
1. 双链表结构体
typedef struct DLNODE
{
int data; //存放结点中的数据
struct DLNODE *prior; //指向前驱结点的指针
struct DLNODE* next; //指向后继结点的指针
}DLNODE;
2. 双链表初始化
/*
method:
创建双链表
param:
dlnode 要操作的顺序表
dat 数组中存放要创建链表的数据
n 要创建单链表的长度
*/
int Create_DLnode(DLNODE** dlnode, int dat[], int n)
{
int i = 0;
DLNODE* p,* q;
*dlnode = (DLNODE*)malloc(sizeof(DLNODE)); //为dlnode分配内存空间
(*dlnode)->data = NULL; //初始化头结点
(*dlnode)->next = NULL;
(*dlnode)->prior = NULL;
p = (*dlnode); //p指针指向头结点
for (int i = 0; i < n; i++)
{
q = (DLNODE*)malloc(sizeof(DLNODE));
q->data = dat[i];
p->next = q;
q->prior = p;
p = q;
}
p->next = NULL; //表尾
return OK;
}
3. 双链表的查询
/*
method:
查询双链表数据
param:
dlnode 要操作的顺序表
x 要查找的元素值
return
返回查找到的该结点
*/
DLNODE* Find_DLnode(DLNODE* dlnode, int x)
{
DLNODE* p;
p = dlnode->next; //这里p指针指向第一个结点
while (p != NULL) //判断是否循环完链表
{
if (p->data == x) //如果该结点正是所查找数据,直接break,返回该结点
return p;
p = p->next;
}
return NULL;
}
4. 双链表的插入
/*
method:
向双链表插入数据
param:
dlnode 要操作的顺序表
x 要插入的元素值
*/
int Insert_DLnode(DLNODE* dlnode, int x)
{
DLNODE* p, * q;
p = dlnode->next; //p指针指向第一个结点
q = (DLNODE*)malloc(sizeof(DLNODE)); //创建一个结点,以供插入
q->data = x;
q->next = NULL;
q->prior = NULL;
while (p != NULL) //循环链表
{
if (p->data < q->data) //按照升序进行插入
{
if (p->next == NULL) //如果这里为空,则链表循环完,直接将该结点插入到链表最后方
{
p->next = q;
q->prior = p;
break;
}
else
p = p->next; //p指向下一个元素
}
else
{ //先假想一下,一链表从中间切开一刀
q->prior = p->prior; //先将要插入的结点两端赋值。即:先将q的前驱,后继进行赋值
q->next = p;
p->prior = q; //然后再将被断开的结点的两端进行赋值。即p的前驱,q的前驱的后继
q->prior->next = q;
break;
}
}
return OK;
}
5. 双链表的删除
/*
method:
向双链表删除数据
param:
dlnode 要操作的顺序表
x 要删除的元素值
*/
int Delete_DLnode(DLNODE* dlnode, int x)
{
DLNODE* p;
p = dlnode->next; //p指针指向第一个结点
while (p != NULL) //循环链表
{
if (p->data == x) //如果找到要删除的结点
{ //假象一下,一链表从中间切开一刀,将中间取出一个结点p
p->next->prior = p->prior; //然后将断开的两端的链表的前驱和后继进行赋值,这里指的是 p的后继的前驱,
p->prior->next = p->next; //和 p的前驱的后继进行赋值
__vcrt_free_normal(p);
return OK;
}
p = p->next;
}
return ERROR;
}
6. 双链表的遍历
/*
method:
遍历双链表的数据
param:
dlnode 要操作的顺序表
*/
void Show_DLnode_data(DLNODE* dlnode)
{
DLNODE* p = dlnode; //p指向单链表的头结点
printf("%p", dlnode); //打印出来头结点指针的地址
while (p->next != NULL) //判断下一个结点是否为空
{
printf("->%d", p->next->data); //打印出来链表中的数据
p = p->next; //遍历单链表
}
printf("\n");
}