//基本上都是照着视频打的。。。
//链表的各种操作方法
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
struct Node
{
int nid;
char msg[20];
struct Node *next;
};
/*
* 操作1:初始化链表
* 参数pHead为链表的头文件,该方法用于将头指针指向NULL, 代表该链表为一个空的链表,
* 从而实现链表的初始化操作
*/
void initLinkList(struct Node **pHead)
{
*pHead = NULL;
printf("操作:>链表初始化成功!\n");
}
/*
*操作2:创建链表结构
*参数pHead为链表的头指针,将该参数进行输入操作后返回即实现了链表的操作
*
*/
struct Node * createLinkList(struct Node *pHead)
{
struct Node *p1, *p2;
int size = 0;
char c; //操作符号
printf("提示:>开始创建链表结构...");
do{
size = size + 1; //将size的值+1
p1 = (struct Node *)malloc(sizeof(struct Node));//p1申请内存空间
printf("编号:>");
scanf("%d", &p1->nid);
printf("内容 :>");
scanf("%s", p1->msg);
//判断该节点是否为链表中的第一个节点
if(size == 1) pHead = p1;
else p2->next = p1;
p2 = p1; //重要:让p2指针指向p1新创建的节点上
printf("继续(y/n)? :> ");
getchar();
scanf("%c", &c);
}while(c == 'y' || c == 'Y');
p2->next = NULL; //将最后一个节点的*next指向NULL
printf("操作:>链表创建完毕!\n");
return pHead; //将头指针返回
}
/*
*操作3:判断链表是否为空
* 参数pHead判断是否指向NULL
*/
int isEmptyLinkList(struct Node *pHead)
{
return pHead == NULL ? 1:0;
}
/*
*操作4:输出链表结构
*参数pHead,使用while循环格式化输出链表结构
*/
void printLinkList(struct Node *pHead)
{
struct Node *p;
if(!isEmptyLinkList(pHead)){
p = pHead; //将p指针指向pHead,避免直接操作原始pHead
printf("## 链表输出:");
do {
printf("[%s]", p->msg);
if (p->next != NULL){
printf(" ->");
}
p = p->next;
}while(p != NULL);
printf("\n");
}else{
printf("提示:>该链表为空!\n");
}
}
/*
*操作5:统计节点的个数
* 参数pHead,通过循环便利节点累加统计节点的个数
*/
int getLinkListNodeCount(struct Node *pHead)
{
struct Node *pTmp;
pTmp = pHead;
int count = 1;
while (pTmp->next != NULL){
count += 1;
pTmp = pTmp->next;
}
return count;
}
/*
*操作6:链表的检索
*参数 pHead, position
*pHead为链表指针, position为检索的链表节点编号
*/
struct Node * seekLinkList(struct Node *pHead, int position)
{
struct Node *pTmp;
int i, nodeCount = getLinkListNodeCount(pHead);
if(position > nodeCount || position <= 0){
printf("错误:>您所指定的节点编号不存在! \n");
} else {
pTmp = pHead;
for (i=0; i<position-1;i++){
pTmp = pTmp->next;
}
return pTmp;
}
}
/*
*操作7:输出指定的链表中的节点数据
*参数结构体指针,输出指针所指向的数据
*/
void printNodeData(struct Node *p)
{
printf("节点信息: ");
printf("[%d, %s]\n", p->nid, p->msg);
}
/*
* 操作8:删除链表指定位置的节点
* 参数position, 获取删除节点的位置,通过seekLinkList方法获取该位置的指针,通过position-1/
* position+1 获取删除节点前置和后置节点指针,便于后续操作
*/
int deleteNodeByPosition(struct Node **p, struct Node *pHead, int position)
{
struct Node *pDelete, *pPrev, *pNext;
int nodeCount = getLinkListNodeCount(pHead);
if (position > nodeCount || position <= 0){
printf("错误:>您输入的节点位置不存在 !\n");
return 0;
}else{
pDelete = seekLinkList(pHead, position); //获取待删除的节点指针
if(pDelete == pHead){ //判断该节点是否为第一个节点
printf("操作:>正在删除第一个节点...\n");
pNext = seekLinkList(pHead, (position+1));
*p = pNext;
}else if(pDelete->next == NULL){ //判断该节点是否为最后一个节点
printf("操作:>正在删除最后一个节点.....\n");
pPrev = seekLinkList(pHead, (position-1));
pPrev->next = NULL;
}else{
printf("操作:> 正在删除链表中的节点.....\n");
pPrev = seekLinkList(pHead, (position-1));
pNext = seekLinkList(pHead, (position+1));
pPrev->next = pNext; //前置节点的*next指针指向后置节点
}
pDelete = NULL; //当前删除的指针置空
return 1;
}
}
/*
*操作9:实现对链表节点的添加操作
*参数:**p, *pHead, position, flag
* 首先判断插入位置是否正确,其次获取插入位置的节点指针, 获取*pPrev, *pNext
*/
int insertLinkListNode(struct Node **p, struct Node *pHead, int position, int flag)
{
struct Node *pThis, *pPrev, *pNext, *pInsert;
int nodeCount = getLinkListNodeCount(pHead);
if(position > nodeCount ||position <= 0){
printf("错误:插入节点的位置数据不存在");
return 0;
}else{
//首先开辟一个节点的内存空间
pInsert = (struct Node *)malloc(sizeof (struct Node));
//为该节点赋值
printf("请输入新的节点信息:\n");
printf("编号:>");
scanf("%d", &pInsert->nid);
printf("内容:>");
scanf("%s", pInsert->msg);
pThis = seekLinkList(pHead, position);
if(pThis == pHead){
if(!flag){
printf("操作:>向第一个节点[前]插入新的节点数据.....\n");
*p = pInsert; //将头指针指向新添加的节点
pInsert->next = pThis; // 将新添加的节点*next1指向原先的第一个节点
}else{
printf("操作:>向第一个节点[后]插入新的节点数据.....\n");
pNext = seekLinkList(pHead, (position + 1));
pThis -> next = pInsert;//
pInsert->next = pNext;
}
}else if(pThis->next == NULL){//链表中的最后一个节点后追加一个节点
if(!flag){
printf("操作:>向最后一个节点[前]插入新的节点数据....\n");
pPrev = seekLinkList(pHead,(position - 1));
pPrev->next = pInsert;
pInsert->next = pThis;
}else{
printf("操作:>向第最后一个节点[后]插入新的数据......\n");
pThis->next = pInsert;
pInsert->next = NULL;
}
}else{//链表中的中间节点
if(!flag){
printf("操作:>向中间节点[前]插入新的节点数据....\n");
pPrev = seekLinkList(pHead, (position - 1));
pPrev->next = pInsert;
pInsert->next = pThis;
}else{
printf("操作:>向中间节点[后]插入新的节点数据......\n");
pNext = seekLinkList(pHead, (position + 1));
pThis->next = pInsert;
pInsert->next = pNext;
}
}
return 1;
}
}
int main(void)
{
struct Node *pHead, *pTmp;
int choise,position,flag,dist;
char selected;
do{
system("clear");
printf("\n\n===================================\n");
printf("\t工程实践:链表的操作\n");
printf("----------------------------------------\n");
printf(" 功能菜单:\n");
printf("\t(1) 初始化链表\n");
printf("\t(2) 创建链表结构\n");
printf("\t(3) 输出链表结构\n");
printf("\t(4) 通过位置检索链表节点\n");
printf("\t(5) 删除链表节点\n");
printf("\t(6) 插入链表节点\n");
printf("\t(7) 退出 \n");
printf("\n========================================\n");
printf("请选择功能:");
scanf("%d", &choise);
switch (choise){
case 1:
initLinkList(&pHead); break;//初始化链表结构
case 2:
pHead = createLinkList(pHead); break;//创建链表结构
case 3:
printLinkList(pHead); break;//输出链表结构
case 4:
printf("请输入需要检索的节点位置(1-%d): >", getLinkListNodeCount(pHead));
scanf("%d", &position);
pTmp = seekLinkList(pHead, position); //检索链表节点
if(pTmp != NULL){
printNodeData(pTmp);//输出节点信息
}
break;
case 5:
printf("请输入需要删除的节点位置(1-%d):>",getLinkListNodeCount(pHead));
scanf("%d", &position);
if(deleteNodeByPosition(&pHead, pHead, position)){
printf("操作:> 第%dg个节点删除成功!\n",position);
printLinkList(pHead); break;//输出链表结构
}else{
printf("操作:>第%d个节点删除失败!\n",position);
}
break;
case 6:
printf("请输入插入节点的位置(1-%d):>", getLinkListNodeCount(pHead));
scanf("%d", &position);
printf("确定插入位置[0. 前置插入 1.后置插入]:>");
scanf("%d", &flag);
if(insertLinkListNode(&pHead, pHead, position, flag)){
printf("操作:> 节点插入成功!\n");
printLinkList(pHead); break;//输出链表结构
}else{
printf("操作:> 节点插入失败!\n");
}
break;
case 7:
exit(0);break;
default:break;
}
printf("\n继续操作?(y/n):> ");
getchar();
scanf("%c", &selected);
}while(selected == 'y' || selected == 'Y');
return 0;
}
链表的各种操作
最新推荐文章于 2024-07-04 15:16:11 发布