代码使用VS2022写的,所以如果要使用其他编译器运行的话,请将scanf_s改回scanf,防止报错
1.线性表
1.1顺序表
包括了定义结构体,顺序表的初始化,在某个位置插入元素,删除特定位置的元素,按位查找、按值查找、在表尾插入元素、打印整张表。
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#define MAX_SIZE 10
typedef struct {
int data[MAX_SIZE];
int length;
}SqList; //定义了一个结构体,结构体里面包含了一个最大长度为10的数组和顺序表当前的长度length,SqList是当前结构体的简称
//顺序表的初始化
void InitList(SqList* L)
{
L->length = 0;
}
//在顺序表L的i位序中插入元素e,要注意区分位序和下标。下标+1=位序,顺序表的第一位元素的下标是从0开始的
//判断插入位置是否合法-->将第i个元素及其后面的元素向后移动一位-->在位置i放入e-->顺序表长度+1
bool List_Insert(SqList* L, int i, int e)
{
if (i > L->length+1 || i < 1 || L->length > MAX_SIZE)
{
printf("非法插入操作!\n");
return false;
}
for (int j = L->length; j >= i; j--)
{
L->data[j] = L->data[j - 1];
}
L->data[i - 1] = e;
L->length++;
return true;
}
//删除顺序表中的位序为i的值,并用e返回
//判断删除位置是否合法-->将第i+1及其后面的元素的位置向前移动一位-->顺序表长度-1
bool List_Delete(SqList* L, int i)
{
if (i > L->length || i < 1)
{
printf("非法删除操作!\n");
return false;
}
for (int j = i; j<L->length; j++)
{
L->data[j - 1] = L->data[j];
}
L->length--;
return true;
}
//按位查找顺序表中的元素
//判断查找位置是否合法-->将被查找的元素直接用函数返回
int Get_List(SqList* L, int i)
{
if (i > L->length || i < 1)
{
printf("非法查找操作!\n");
return -999;
}
else
{
return L->data[i - 1];
}
}
//按值查找顺序表中的元素
//遍历顺序表中的每个元素并且与e比对-->返回元素的位序,因为是返回位序,所以i要加一才行
int Get_List_Locate(SqList* L, int e)
{
for (int i = 0; i <= L->length; ++i)
{
if (L->data[i] == e)
return i + 1;
else
{
return -1;
}
}
}
//打印整张顺序表
//直接遍历整张表同时输出每一个元素
void Prin_List(SqList* L)
{
printf("顺序表:");
for (int i = 0; i < L->length; ++i)
{
printf("%d\t", L->data[i]);
}
printf("\n");
}
//在尾部插入一个元素
//判断插入元素是否合法-->插入元素,长度+1
bool Insert_List_Tail(SqList* L, int e)
{
if (L->length >= MAX_SIZE)
{
printf("顺序表已满,无法插入!\n");
return false;
}
L->data[L->length] = e;
L->length++;
return true;
}
int main()
{
SqList L;
InitList(&L);
/*
使用上面的函数......
*/
return 0;
}
1.2单链表(带头节点)
包括了定义结构体,链表的初始化,链表的判空,统计链表的长度,头插法和尾插法创建链表,按位序插入节点,按值查找,按位查找,按值删除,按位删除,打印整张链表。
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
//定义一个链表结构体
//LNode是struct LNode的简称,LinkList是指向这个结构体的指针
typedef struct LNode {
int data;
struct LNode* next;
}LNode, *LinkList;
//初始化链表
//创建头节点-->判断是否有足够的内存给Phead节点-->令头节点的指针指向NULL
bool Init_LinkList(LinkList* pHead)
{
*pHead = (LNode*)malloc(sizeof(LNode));
if (pHead == NULL)
return false;
(*pHead)->next = NULL;
return true;
}
//判断链表是否位空
//看头节点的指针是否指向NULL,用return返回
bool Empty_LinkList(LinkList pHead)
{
if (pHead->next == NULL)
return true;
else
{
return false;
}
}
//统计链表长度(节点的个数)
//从头节点开始遍历整个表。经过一个节点就+1,用return返回个数
int Length_LinkList(LinkList pHead)
{
int count = 0;
for (LNode* z = pHead->next; z != NULL; z = z->next)
{
++count;
}
return count;
}
//头插法创建链表(倒叙输出)
//创建一个新的节点-->新节点的指针指向头节点的next-->头节点的next指向新节点。顺序不可乱
LinkList Create_HEAD_LinkList(LinkList pHead)
{
int val;
printf("请输入要录入链表的数字(输入999停止):");
scanf_s("%d", &val);
while (val != 999)
{
LNode* pTemp = (LNode*)malloc(sizeof(LNode));
pTemp->next = pHead->next;
pHead->next = pTemp;
pTemp->data = val;
printf("请输入要录入链表的数字(输入999停止):");
scanf_s("%d", &val);
}
return pHead;
}
//尾插法创建链表
//创建2个指针,一个临时节点的指针指向临时节点,另一个是尾节点的指针指向表尾-->创建新节点并且使尾节点指针指向它-->新节点的next指向NULL
LinkList Create_TAIL_LinkList(LinkList pHead)
{
int val;
LNode* pTail = pHead;
LNode* pTemp;
printf("请输入要录入链表的数字(输入999停止):");
scanf_s("%d", &val);
while (val != 999)
{
pTemp = (LNode*)malloc(sizeof(LNode));
pTemp->data = val;
pTail->next = pTemp;
pTail = pTemp;
printf("请输入要录入链表的数字(输入999停止):");
scanf_s("%d", &val);
}
pTail->next = NULL;
return pHead;
}
//按位序插入元素
//判断插入是否合法-->遍历链表找到插入位置-->创建新的节点-->修改前后指针完成插入,一定要先后再前修改
void Insert_LinkList(LinkList pHead, int i, int e)
{
if (i<1 || i>Length_LinkList(pHead) + 1)
return;
LNode* p = pHead;
int j = 0;
while (p != NULL && j < i - 1)
{
p = p->next;
j++;
}
LNode* pTemp = (LNode*)malloc(sizeof(LNode));
pTemp->data = e;
pTemp->next = p->next;
p->next = pTemp;
return;
}
//按值查找
//从头开始遍历链表,找到与之匹配的值之后直接在子函数内printf他的位置
void GET_LinkList(LinkList pHead, int e)
{
LNode* p = pHead->next;
int i = 0;
while(p != NULL && p->data != e)
{
p = p->next;
++i;
}
printf("该元素 %d 位于第%d位\n", e, i + 1);
return;
}
//按位查找
//从头开始遍历链表,找到与之匹配的位序之后直接在子函数内printf他的data
void GET_LOCAL_LinkList(LinkList pHead, int i)
{
if(i < 1 || i > Length_LinkList(pHead))
{
printf("非法查找!\n");
return;
}
LNode* p = pHead->next;
int j = 0;
while (p->next != NULL && j<i-1)
{
p = p->next;
++j;
}
printf("第%d位的元素的值为%d\n", i, p->data);
return;
}
//按位序删除节点
//从头开始遍历链表找到与之对应的位序的节点-->free掉
void Delete_LOCAL_LinkList(LinkList pHead, int i)
{
if (i < 1 || i > Length_LinkList(pHead))
{
printf("非法删除!\n");
return;
}
LNode* p = pHead;
int j = 0;
for (j; j < i - 1; j++)
{
p = p->next;
}
LNode* q = p->next; //新建一个指针q指向待删除的节点
if (q->next == NULL)
p->next = NULL;
else
{
p->next = q->next; //直接让p指向下下个节点跳过q,完成删除
}
free(q);
printf("已删除节点%d\n",i);
return;
}
//按值删除节点
//从头开始遍历链表-->找到与之对应的值的节点-->删除该节点
void Delete_LinkList(LinkList pHead, int e)
{
int count = 1;
if (Length_LinkList(pHead) == 0)
{
printf("链表为空无法删除!\n");
return;
}
LNode* prev = pHead; //新建一个指针用来指向当前节点的前一个节点
LNode* p = pHead->next;
while (p != NULL)
{
if (p->data == e)
{
prev->next = p->next; //让被删除的前一个节点直接指向被删除节点的下一个节点
free(p);
printf("已删除节点%d\n",count);
return;
}
prev = p;
p = p->next;
++count;
}
printf("链表中未找到值为%d的节点\n", e);
return;
}
//打印链表
//从头开始遍历链表-->依次输出每个节点的data
void Print_LinkList(LinkList pHead)
{
int i = 1;
LNode* p = pHead->next;
for(; p != NULL ;)
{
printf("第%d号节点的值为%d\n",i, p->data);
p = p->next;
++i;
}
return;
}
int main()
{
LinkList pHead;
printf("初始化%d\n",Init_LinkList(&pHead));
printf("判空%d\n",Empty_LinkList(pHead));
printf("初始化之后的长度=%d\n", Length_LinkList(pHead));
printf("\n------------------------------\n");
Create_HEAD_LinkList(pHead);
printf("头插法之后的长度=%d\n", Length_LinkList(pHead));
printf("\n------------------------------\n");
//Create_TAIL_LinkList(pHead);
//printf("尾插法之后的长度=%d\n", Length_LinkList(pHead));
//printf("\n------------------------------\n");
Insert_LinkList(pHead,1,100);
printf("中间插入之后的长度=%d\n", Length_LinkList(pHead));
printf("\n------------------------------\n");
//GET_LinkList(pHead, 55);
//GET_LOCAL_LinkList(pHead, 3);
//printf("\n------------------------------\n");
//Delete_LOCAL_LinkList(pHead, 2);
//printf("删除之后的长度=%d\n", Length_LinkList(pHead));
//printf("\n------------------------------\n");
Print_LinkList(pHead);
printf("\n------------------------------\n");
Delete_LinkList(pHead,5);
Print_LinkList(pHead);
return 0;
}
1.3双链表(带头结点)
包括了定义结构体,链表的初始化,链表的判空,统计链表的长度,头插法和尾插法创建链表,按位序插入节点,按值查找,按位查找,按位删除,打印整张链表(正序逆序),释放整张链表。
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
//定义了一个双链表的结构体,名字是DNode,每个节点都有两个指针——prior和next
typedef struct DNode
{
int data;
struct DNode* prior, * next;
}DNode, *DLinkList;
//双链表的初始化
//创建头节点并且判断内存是否正常分配后直接让头节点的前后指针指向NULL
bool Init_DLinkList(DLinkList* pHead)
{
*pHead = (DNode*)malloc(sizeof(DNode));
if (*pHead == NULL)
return false;
(*pHead)->prior = NULL;
(*pHead)->next = NULL;
return true;
}
//双链表的判空
//看头节点的next指针是否指向了NULL
bool Empty_DLinkList(DLinkList pHead)
{
if (pHead->next == NULL)
return true;
else
{
return false;
}
}
//双链表的长度计算
//创建一个临时指针=头节点的next,遍历整个链表经过一个节点就+1,最后函数返回结果
int Length_DLinkList(DLinkList pHead)
{
int count = 0;
DNode* p = pHead->next;
for (; p != NULL; p = p->next)
++count;
return count;
}
//头插法创建双链表(结果为倒叙)
//创建一个临时节点-->新节点的next指向头节点的next-->新节点的prior指向头节点-->修改头节点之后节点的prior指针-->头节点的next指向新节点
DLinkList Creat_HEAD_DLinkList(DLinkList pHead)
{
DNode* pTemp;
int val;
printf("请输入需要插入的元素(输入999结束):");
scanf_s("%d", &val);
while (val != 999)
{
pTemp = (DNode*)malloc(sizeof(DNode));
pTemp->data = val;
pTemp->next = pHead->next;
pTemp->prior = pHead;
if (pHead->next != NULL)
{
pHead->next->prior = pTemp;
}
pHead->next = pTemp;
printf("请输入需要插入的元素(输入999结束):");
scanf_s("%d", &val);
}
return pHead;
}
//尾插法创建双链表
//创造一个新节点pTemp-->令前节点next成为新节点的next-->新节点prior指向前一个节点-->前一个节点的next指向新节点-->移动p指针使其指向新节点
bool Creat_TAIL_DLinkList(DLinkList pHead)
{
DNode* p = pHead;
DNode* pTemp;
int val;
printf("请输入需要插入的元素(输入999结束):");
scanf_s("%d", &val);
while (val != 999)
{
pTemp = (DNode*)malloc(sizeof(DNode));
pTemp->next = p->next;
pTemp->prior = p;
p->next = pTemp;
p = p->next;
pTemp->data = val;
printf("请输入需要插入的元素(输入999结束):");
scanf_s("%d", &val);
}
p->next = NULL;
return true;
}
//打印链表(从头开始)
//创建一个指针使其指向头节点的next,遍历每一个节点输出data
void Print_DLinkList(DLinkList pHead)
{
int i=1;
DNode* p = pHead->next;
for (;p != NULL;)
{
printf("第%d个元素为%d\n", i, p->data);
p = p->next;
++i;
}
printf("\n");
return;
}
//打印链表(从后往前)
//创建一个指针使其指向尾节点遍历每一个节点输出data
void Print_TAIL_DLinkList(DLinkList Phead)
{
int i = 1;
DNode* p = Phead;
while (p->next != NULL)
{
p = p->next;
}
while (p->prior != NULL)
{
printf("第%d个元素为:%d\n", i, p->data);
p = p->prior;
++i;
}
printf("\n");
return;
}
//按值查找
//创建一个指针指向头节点的next-->开始遍历链表找到与之相对应的值输出其位序
void Get_DLinkList(DLinkList pHead, int e)
{
int i = 1; //头节点不存数据,所以直接从1开始,而非从零开始
DNode* p = pHead->next;
while (p != NULL)
{
if (p->data == e)
{
printf("元素%d位于第%d位\n", e, i);
p = p->next;
i++;
continue;
}
p = p->next;
i++;
}
return;
}
//按位查找
//创建一个指针指向头节点的next-->开始遍历链表找到与之相对应的位序输出其data
void Get_LOACL_DLinkList(DLinkList pHead, int i)
{
DNode* p = pHead->next;
if (p == NULL || i<1 || i>Length_DLinkList(pHead))
{
printf("无效查询!");
return;
}
int j = 1;
while (j<i)
{
p = p->next;
j++;
}
printf("第%d位的元素为%d\n", i, p->data);
return;
}
//按位删除
//创建一个指针p指向头节点-->开始遍历链表找到被删除节点的前一位-->再创建一个指针q指向被被删除节点(p的next)-->令p的next指向q的next-->如果被删除节点不是最后一个节点,q的下一个节点的prior指向p-->释放q
void Delete_LOCAL_DLinkList(DLinkList pHead, int i)
{
if (i<1 || i>Length_DLinkList(pHead))
{
printf("无效删除!");
return;
}
DNode* p = pHead;
int j = 0;
while (j<i-1)
{
p = p->next;
j++;
}
DNode* q = p->next;
p->next = q->next;
if (q->next != NULL)
{
q->next->prior = p;
}
free(q);
return;
}
//清除整张链表
//创建一个指针p指向头节点后依次遍历链表释放内存
void Delete_ALL_DLinkList(DLinkList pHead)
{
DNode* p = pHead;
DNode* q;
while (p != NULL)
{
q = p;
p = p->next;
free(q);
}
printf("链表已清除\n");
return;
}
int main()
{
DLinkList pHead;
printf("初始化:%d\n", Init_DLinkList(&pHead));
printf("判空:%d\n", Empty_DLinkList(pHead));
printf("长度:%d\n", Length_DLinkList(pHead));
printf("\n------------------------------\n");
//Creat_HEAD_DLinkList(pHead);
//printf("长度:%d\n", Length_DLinkList(pHead));
//printf("\n------------------------------\n");
Creat_TAIL_DLinkList(pHead);
printf("长度:%d\n", Length_DLinkList(pHead));
Print_DLinkList(pHead);
printf("\n------------------------------\n");
//Print_TAIL_DLinkList(pHead);
//printf("\n------------------------------\n");
//Get_DLinkList(pHead,2);
//Get_LOACL_DLinkList(pHead,7);
//Delete_LOCAL_DLinkList(pHead, 2);
//Print_DLinkList(pHead);
//printf("\n------------------------------\n");
Delete_ALL_DLinkList(pHead);
return 0;
}
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
//创建结构体
typedef struct LNode {
int data;
LNode* next;
}LNode, *LinkList;
//循环单链表的初始化
//创建一个头节点并且令头节点的next指向自己
bool Init_LinkList(LinkList* pHead)
{
(*pHead) = (LNode*)malloc(sizeof(LNode));
if (pHead == NULL)
{
printf("Initialization false!\n");
return false;
}
(*pHead)->next = (*pHead);
printf("Initialization successed!\n");
return true;
}
//循环单链表的判空
//直接判断头节点的next是否指向自己即可
bool Empty_LinkList(LinkList* pHead)
{
if((*pHead)->next == (*pHead))
{
printf("Error node is empty!\n");
return true;
}
return false;
}
//计算循环单链表的长度
//通过建立一个临时指针p来遍历链表,经过一个节点就令count+1
int Length_LinkList(LinkList* pHead)
{
int count = 0;
LinkList p = (*pHead)->next;
while (p != (*pHead)) //这里不能像双链表或者单链表一样写成 p != NULL 因为在循环单链表中,链表的结尾是从新指向头节点的,所以一个有效的循环单链表的next是不会出现NULL的。
{
++count;
p = p->next;
}
return count;
}
//头插法建立链表
//建立一个新节点,使得新节点的next指向头节点next,由于头节点的next指向了自己,所以新节点的next也是指向头节点的,最后修改头节点的next指向新节点完成插入
LinkList Create_HEAD_LinkList(LinkList* pHead)
{
LNode* pTemp;
int val;
printf("Enter number(end whit 999):");
scanf_s("%d", &val);
while (val != 999)
{
pTemp = (LNode*)malloc(sizeof(LNode));
pTemp->next = (*pHead)->next;
(*pHead)->next = pTemp;
pTemp->data = val;
printf("Enter number(end whit 999):");
scanf_s("%d", &val);
}
return *pHead;
}
//尾插法创建链表
//创建一个临时节点的指针,再创建一个指针指向头节点方便后续操作。临时指针指向临时节点,表尾指针指向临时节点,移动表尾指针
LinkList Create_TAIL_LinkList(LinkList* pHead)
{
int val;
LNode* pTemp;
LNode* pTail = (*pHead);
printf("Enter number(end whit 999):");
scanf_s("%d", &val);
while (val != 999)
{
pTemp = (LNode*)malloc(sizeof(LNode));
pTail->next = pTemp; //尾节点指针指向新节点
pTemp->next = (*pHead); //新节点的next指向头节点形成循环
pTail = pTemp; //移动表尾指针到新节点
pTemp->data = val; //新节点赋值
printf("Enter number(end whit 999):");
scanf_s("%d", &val);
}
return *pHead;
}
//按位序插入新节点
//建立一个临时的指针指向头节点,开始遍历链表找到插入节点的前一个节点-->创建新节点使得临时指针的next指向新节点的next-->最后临时指针指向新节点完成插入
bool Insert_LinkList(LinkList* pHead,int i,int e)
{
if (i<1 || i>Length_LinkList(pHead) + 1) return false;
int j = 0;
LNode* p = (*pHead);
while (p != NULL && j<i-1)
{
p = p->next;
++j;
}
LNode* pTemp = (LNode*)malloc(sizeof(LNode));
pTemp->next = p->next;
p->next = pTemp;
p->data = e;
return true;
}
//按位序删除节点
//先创建一个临时指针指向头节点,从头节点开始遍历链表,找到要删除节点的前一个节点,修改被删除节点前后节点的指针
bool Delete_LinkList(LinkList* pHead, int i)
{
if (Empty_LinkList(pHead))
{
printf("Error,LinkList is null!\n");
return false;
}
LNode* p = (*pHead);
for (int j = 0; j < i - 1; ++j)
{
p = p->next;
}
LNode* q = p->next;
p->next = p->next->next;
free(q);
return true;
}
//按值查找节点位置
//创建一个临时指针指向头节点的next,开始遍历链表并且对比每个节点的data是否等于查找的值,最后返回指针给主函数
LinkList Get_LinkList(LinkList* pHead, int e)
{
if (Empty_LinkList(pHead))
{
printf("Error,LinkList is null!\n");
exit;
}
LNode* p = (*pHead)->next;
int j = 1;
for (j; j < Length_LinkList(pHead)+1; ++j)
{
if (p->data == e)
{
printf("%dhas been successfully found!\n",e);
return p;
}
else
{
p = p->next;
}
}
if (p == (*pHead))
{
printf("No such %d!\n", e);
}
exit;
}
//打印链表
//建立一个指针指向头节点的next,遍历链表打印每个节点的data
void Print_LinkList(LinkList* pHead)
{
if (Empty_LinkList(pHead))
{
printf("Error,LinkList is null!\n");
exit;
}
int i = 1;
LinkList p = (*pHead)->next;
while (p !=(*pHead))
{
printf("Node %d is %d\n", i, p->data);
++i;
p = p->next;
}
return;
}
//销毁循环单链表
//先建立2个指针p和q,p指向头节点的下一个节点,q指向p。先移动p至下一个节点然后再释放q。等到循环结束之后再将头节点释放完成链表的销毁
bool Destory_LinkList(LinkList* pHead)
{
LinkList p = (*pHead)->next;
LinkList q;
while (p->next != (*pHead))
{
q = p;
p = p->next;
free(q);
}
free(p);
printf("LinkList has destory!\n");
return true;
}
int main()
{
LinkList pHead;
Init_LinkList(&pHead);
Create_HEAD_LinkList(&pHead);
printf("Length=%d\n", Length_LinkList(&pHead));
Print_LinkList(&pHead);
Destory_LinkList(&pHead);
return 0;
}
1.4循环单链表
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
//创建结构体
typedef struct LNode {
int data;
LNode* next;
}LNode, *LinkList;
//循环单链表的初始化
//创建一个头节点并且令头节点的next指向自己
bool Init_LinkList(LinkList* pHead)
{
(*pHead) = (LNode*)malloc(sizeof(LNode));
if (pHead == NULL)
{
printf("Initialization false!\n");
return false;
}
(*pHead)->next = (*pHead);
printf("Initialization successed!\n");
return true;
}
//循环单链表的判空
//直接判断头节点的next是否指向自己即可
bool Empty_LinkList(LinkList* pHead)
{
if((*pHead)->next == (*pHead))
{
printf("Error node is empty!\n");
return true;
}
return false;
}
//计算循环单链表的长度
//通过建立一个临时指针p来遍历链表,经过一个节点就令count+1
int Length_LinkList(LinkList* pHead)
{
int count = 0;
LinkList p = (*pHead)->next;
while (p != (*pHead)) //这里不能像双链表或者单链表一样写成 p != NULL 因为在循环单链表中,链表的结尾是从新指向头节点的,所以一个有效的循环单链表的next是不会出现NULL的。
{
++count;
p = p->next;
}
return count;
}
//头插法建立链表
//建立一个新节点,使得新节点的next指向头节点next,由于头节点的next指向了自己,所以新节点的next也是指向头节点的,最后修改头节点的next指向新节点完成插入
LinkList Create_HEAD_LinkList(LinkList* pHead)
{
LNode* pTemp;
int val;
printf("Enter number(end whit 999):");
scanf_s("%d", &val);
while (val != 999)
{
pTemp = (LNode*)malloc(sizeof(LNode));
pTemp->next = (*pHead)->next;
(*pHead)->next = pTemp;
pTemp->data = val;
printf("Enter number(end whit 999):");
scanf_s("%d", &val);
}
return *pHead;
}
//尾插法创建链表
//创建一个临时节点的指针,再创建一个指针指向头节点方便后续操作。临时指针指向临时节点,表尾指针指向临时节点,移动表尾指针
LinkList Create_TAIL_LinkList(LinkList* pHead)
{
int val;
LNode* pTemp;
LNode* pTail = (*pHead);
printf("Enter number(end whit 999):");
scanf_s("%d", &val);
while (val != 999)
{
pTemp = (LNode*)malloc(sizeof(LNode));
pTail->next = pTemp; //尾节点指针指向新节点
pTemp->next = (*pHead); //新节点的next指向头节点形成循环
pTail = pTemp; //移动表尾指针到新节点
pTemp->data = val; //新节点赋值
printf("Enter number(end whit 999):");
scanf_s("%d", &val);
}
return *pHead;
}
//按位序插入新节点
//建立一个临时的指针指向头节点,开始遍历链表找到插入节点的前一个节点-->创建新节点使得临时指针的next指向新节点的next-->最后临时指针指向新节点完成插入
bool Insert_LinkList(LinkList* pHead,int i,int e)
{
if (i<1 || i>Length_LinkList(pHead) + 1) return false;
int j = 0;
LNode* p = (*pHead);
while (p != NULL && j<i-1)
{
p = p->next;
++j;
}
LNode* pTemp = (LNode*)malloc(sizeof(LNode));
pTemp->next = p->next;
p->next = pTemp;
pTemp->data = e;
return true;
}
//按位序删除节点
//先创建一个临时指针指向头节点,从头节点开始遍历链表,找到要删除节点的前一个节点,修改被删除节点前后节点的指针
bool Delete_LinkList(LinkList* pHead, int i)
{
if (Empty_LinkList(pHead))
{
printf("Error,LinkList is null!\n");
return false;
}
LNode* p = (*pHead);
for (int j = 0; j < i - 1; ++j)
{
p = p->next;
}
LNode* q = p->next;
p->next = p->next->next;
free(q);
return true;
}
//按值查找节点位置
//创建一个临时指针指向头节点的next,开始遍历链表并且对比每个节点的data是否等于查找的值,最后返回指针给主函数
LinkList Get_LinkList(LinkList* pHead, int e)
{
if (Empty_LinkList(pHead))
{
printf("Error,LinkList is null!\n");
exit;
}
LNode* p = (*pHead)->next;
int j = 1;
for (j; j < Length_LinkList(pHead)+1; ++j)
{
if (p->data == e)
{
printf("%dhas been successfully found!\n",e);
return p;
}
else
{
p = p->next;
}
}
if (p == (*pHead))
{
printf("No such %d!\n", e);
}
exit;
}
//打印链表
//建立一个指针指向头节点的next,遍历链表打印每个节点的data
void Print_LinkList(LinkList* pHead)
{
if (Empty_LinkList(pHead))
{
printf("Error,LinkList is null!\n");
exit;
}
int i = 1;
LinkList p = (*pHead)->next;
while (p !=(*pHead))
{
printf("Node %d is %d\n", i, p->data);
++i;
p = p->next;
}
return;
}
//销毁循环单链表
//先建立2个指针p和q,p指向头节点的下一个节点,q指向p。先移动p至下一个节点然后再释放q。等到循环结束之后再将头节点释放完成链表的销毁
bool Destory_LinkList(LinkList* pHead)
{
LinkList p = (*pHead)->next;
LinkList q;
while (p->next != (*pHead))
{
q = p;
p = p->next;
free(q);
}
free((*pHead));
printf("LinkList has destory!\n");
return true;
}
int main()
{
LinkList pHead;
Init_LinkList(&pHead);
Create_HEAD_LinkList(&pHead);
return 0;
}
2.栈
2.1顺序栈
首先定义了栈的结构体,随后是对栈的初始化和判空操作,出栈和入栈
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
//定义栈的最大容量
#define MAX_SIZE 10
//定义栈的结构体,名字为SqStack
typedef struct {
int data[MAX_SIZE];
int top;
}SqStack;
//初始化栈
//令栈的指针为-1
bool Init_SqStack(SqStack *s)
{
(*s).top = -1;
return true;
}
//判断栈是否为空
//检查top指针是否为-1
bool Empty_SqStack(SqStack* s)
{
if ((*s).top == -1)
return true;
else
{
return false;
}
}
//判断栈是否满
//看top指针是否为 MAX_SIZE - 1
bool Full_SqStack(SqStack* s)
{
if ((*s).top == MAX_SIZE - 1)
return true;
else
{
return false;
}
}
//入栈
//判断是否可以入栈-->元素入栈后修改指针
bool Push_SqStack(SqStack* s, int e)
{
if (Full_SqStack(s))
{
printf("栈已满无法入栈!\n");
return false;
}
else
{
(*s).data[++(*s).top] = e; //++s.top:首先,s.top 的值会增加1。这是前置递增操作,意味着先增加 s.top 的值,然后再使用这个新的值。
return true; //s.data[...] = e;:然后,将新值 e 存入 s.data 数组中由 s.top 索引指定的位置。
}
}
//出栈
//从顶元素开始弹出并且令指针递减
bool Pop_SqStack(SqStack* s)
{
int x;
if (Empty_SqStack(s))
{
printf("栈已空无法出栈!\n");
return false;
}
else
{
x = (*s).data[(*s).top--];
printf("元素:%d 已出栈!\n", x);
return true;
} //注意出入栈的时候指针的增减顺序,入栈是先增,出栈是后减
}
int main()
{
SqStack s;
printf("初始化:%d\n", Init_SqStack(&s));
printf("判空:%d\n", Empty_SqStack(&s));
printf("判满:%d\n", Full_SqStack(&s));
printf("\n------------------------\n");
for (int i = 1; i <MAX_SIZE+1; ++i)
{
Push_SqStack(&s, i);
}
printf("\n------------------------\n");
for (int i = 1; i < MAX_SIZE + 1; ++i)
{
Pop_SqStack(&s);
}
printf("判满:%d\n", Full_SqStack(&s));
printf("判空:%d\n", Empty_SqStack(&s));
return 0;
}
2.2链栈(带头节点)
首先定义了栈的结构体,随后是对栈的初始化和判空操作,出栈和入栈
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
//定义链栈的结构体
typedef struct LNode {
int data;
struct LNode* next;
}LNode, *LinkStack;
//初始化栈
//创建一个头节点,让头节点的指针指向null,并且头节点拿来存栈的长度
bool Init_LinkStack(LinkStack* pStack)
{
(*pStack) = (LNode*)malloc(sizeof(LNode));
if ((*pStack) == NULL)
return false;
(*pStack)->next = NULL;
(*pStack)->data = 0;
return true;
}
//判断栈是否为空
//检查头节点的next是否为NULL
bool Empty_LinkStack(LinkStack* pStack)
{
if ((*pStack)->next == NULL)
{
return true;
}
else
{
return false;
}
}
//查询栈的长度
//通过读取头节点的data即可
int Length_LinkStack(LinkStack* pStack)
{
return (*pStack)->data;
}
//查看栈顶
//直接读取头节点下一个节点的数据
int Get_TOP_LinkStacik(LinkStack* pStack)
{
return (*pStack)->next->data;
}
//入栈
//创造一个新节点-->新节点的next指向头节点的next-->头节点指向新节点-->长度+1
bool Push_LinkStack(LinkStack* pStack, int e)
{
LNode* pTemp = (LNode*)malloc(sizeof(LNode));
pTemp->data = e;
pTemp->next = (*pStack)->next;
(*pStack)->next = pTemp;
(*pStack)->data++;
return true;
}
//出栈
//创建一个临时节点并且指针指向第一个节点,修改头节点的指针指向出栈节点的下一个节点,最后释放出栈节点并且长度-1
bool Pop_LinkStack(LinkStack* pStack)
{
LNode* pTemp = (*pStack)->next;
(*pStack)->next = pTemp->next;
printf("元素:%d已出栈\n", pTemp->data);
free(pTemp);
(*pStack)->data--;
return true;
}
//连续录入元素创建栈
//通过循环不断重复入栈操作
bool Create_LinkStack(LinkStack* pStack)
{
LNode* pTemp;
int val;
printf("请输入入栈元素(输入999结束):");
scanf_s("%d", &val);
while (val != 999)
{
pTemp = (LNode*)malloc(sizeof(LNode));
pTemp->data = val;
pTemp->next = (*pStack)->next;
(*pStack)->next = pTemp;
(*pStack)->data++;
printf("请输入入栈元素(输入999结束):");
scanf_s("%d", &val);
}
return true;
}
int main()
{
LinkStack pStack;
Init_LinkStack(&pStack);
printf("判空:%d\n", Empty_LinkStack(&pStack));
printf("长度:%d\n", Length_LinkStack(&pStack));
printf("\n---------------------------------\n");
Push_LinkStack(&pStack, 100);
printf("判空:%d\n", Empty_LinkStack(&pStack));
printf("长度:%d\n", Length_LinkStack(&pStack));
printf("\n---------------------------------\n");
printf("栈顶元素:%d\n", Get_TOP_LinkStacik(&pStack));
/*
Pop_LinkStack(&pStack);
printf("判空:%d\n", Empty_LinkStack(&pStack));
printf("长度:%d\n", Length_LinkStack(&pStack));
printf("\n---------------------------------\n");
Create_LinkStack(&pStack);
printf("判空:%d\n", Empty_LinkStack(&pStack));
printf("长度:%d\n", Length_LinkStack(&pStack));
printf("\n---------------------------------\n");
Pop_LinkStack(&pStack);
printf("判空:%d\n", Empty_LinkStack(&pStack));
printf("长度:%d\n", Length_LinkStack(&pStack));
printf("\n---------------------------------\n");
*/
return 0;
}
3.队列
3.1队列_顺序表
#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
#define MAX_SIZE 100
typedef struct {
int data[MAX_SIZE];
int front;
int rear;
}SqQueue;
//初始化队列
//让头尾指针指向零
void Init_SqQueue(SqQueue* Q)
{
Q->front = Q->rear = 0;
}
//队列的判空
//看头尾指针是否相等
bool Empty_SqQueue(SqQueue* Q)
{
if (Q->front == Q->rear)
{
return true;
}
else
{
return false;
}
}
//判断队列是否满
//看尾指针是否等于 MAX_SIZE - 1
bool Full_SqQueue(SqQueue* Q)
{
if (Q->rear == MAX_SIZE - 1)
{
return true;
}
else
{
return false;
}
}
//入队操作
//将元素赋值给rear所指向的data。rear++
bool Enter_SqQueue(SqQueue* Q,int e)
{
if (Full_SqQueue(Q)) return false;
Q->data[Q->rear] = e;
Q->rear++;
return true;
}
//出队操作
//向后移动头指针
bool Out_SqQueue(SqQueue* Q)
{
if (Empty_SqQueue(Q)) return false;
Q->front++;
return true;
}
//输出队列中的元素
//依次输出头指针指向的data
void Print_SqQueue(SqQueue* Q)
{
if (Empty_SqQueue(Q)) exit;
int i=Q->front;
while (i < Q->rear)
{
printf("%d\n", Q->data[i]);
++i;
}
}
int main()
{
SqQueue Q;
//**********
return 0;
}