#include<stdio.h>
#include<stdlib.h>
/*
1、带头结点的链表:头节点本身不存元素数据,但头节点的next指针指向第一个节点;
2、若带头结点,则头指针指向头节点(换句话说:头指针等于头节点的地址)。
*/
/*
链表带头结点的优势:
1、第一个位置插入和删除更方便;
2、统一空链表和非空链表的处理:当链表为空时,不带头结点链表的头指针为NULL,
而带头结点链表的头指针仍然为指向节点的指针,无需特殊操作。
*/
typedef struct listNode
{
//头节点的data数据存链表的长度
int nodeData;
struct listNode* nextNode; //Attention nextNode !!!
}listNode, * singleLinkList;
//listNode强调单个节点,singleLinkList强调链表本身。
bool initLinkList(singleLinkList& myList);
//头插法添加元素
void addAfterHead(singleLinkList& myList, int myData);
//尾插法添加元素
void addAfterTail(singleLinkList& myList, int myData);
//此处的myTarget是位序,是从1开始的,不是从0开始的索引!!!
listNode* getNode(const singleLinkList& myList, int myTarget);
bool insertNode(singleLinkList& myList, int myTarget, int myNodeData);
bool removeNode(singleLinkList& myList, int myTarget, int& myNodeData);
//链表逆序处理
void reverseList(singleLinkList& myList);
//链表元素显示
void displayLinkList(const singleLinkList& myList);
int main()
{
singleLinkList myListA;
initLinkList(myListA);
printf("Add after tail : \n");
for(int i = 1; i <= 10; i++)
{
addAfterTail(myListA, i*i);
}
displayLinkList(myListA);
reverseList(myListA);
printf("After reversing : \n");
displayLinkList(myListA);
return 0;
}
bool initLinkList(singleLinkList& myList)
{
//注意:表达式本身是有值的!!!
if((myList = (listNode*)(malloc(sizeof(listNode)))))
{
myList->nodeData = 0;
myList->nextNode = NULL;
myList->nodeData = 0;
return true;
}
else
{
myList = NULL;
printf("Failed to construct !\n");
return false;
}
}
listNode* getNode(const singleLinkList& myList, int myTarget)
{
/*
可以执行此操作的条件:
1、目标位序没有超过链表的范围;
2、若目标位序为头节点,即 myTarget = 0,则返回头节点。
*/
if((0 <= myTarget) && (myTarget <= myList->nodeData))
{
listNode* myNode = myList;
int i = 0;
while(i != myTarget)
{
myNode = myNode->nextNode;
i += 1;
}
return myNode;
}
else
{
printf("Your target is out of range !!!\n");
return NULL;
}
}
bool insertNode(singleLinkList& myList, int myTarget, int myNodeData)
{
/*
执行插入操作的条件:
1、目标位置的上一个位置在链表的范围内(包括头指针);
2、插入元素后,将链表长度+1。
*/
if(getNode(myList, myTarget -1))
{
listNode* LA;
initLinkList(LA);
LA->nextNode = getNode(myList, myTarget -1)->nextNode;
LA->nodeData = myNodeData;
getNode(myList, myTarget -1)->nextNode = LA;
myList->nodeData += 1;
return true;
}
else
{
printf("Your target is out of range !!!\n");
return false;
}
}
bool removeNode(singleLinkList& myList, int myTarget, int& myNodeData)
{
/*
执行删除元素的条件是:
1、链表不为空;
2、(且)删除目标的上一个位置在链表范围内(包括头节点);
3、执行一次删除操作,链表长度-1。
*/
if((getNode(myList, myTarget-1)))
{
myNodeData = getNode(myList, myTarget-1)->nextNode->nodeData;
getNode(myList, myTarget-1)->nextNode = getNode(myList, myTarget-1)->nextNode->nextNode;
free(getNode(myList, myTarget-1));
myList->nodeData -= 1;
return true;
}
else
{
printf("Your target is out of range !!!\n");
return false;
}
}
void displayLinkList(const singleLinkList& myList)
{
if(myList->nodeData != 0)
{
listNode* LA = myList->nextNode;
int i = 1;
while(i <= myList->nodeData)
{
printf("listNode %d is %d , its address is %d , and its next address is %d .\n", i, LA->nodeData, LA, LA->nextNode);
LA = LA->nextNode;
i += 1;
}
printf("\n");
}
else
{
printf("Your linkList is empty !!!\n");
}
}
void addAfterHead(singleLinkList& myList, int myData)
{
listNode* myFirstNode;
initLinkList(myFirstNode);
myFirstNode->nextNode = myList->nextNode;
myFirstNode->nodeData = myData;
myList->nextNode = myFirstNode;
myList->nodeData += 1;
}
void addAfterTail(singleLinkList& myList, int myData)
{
listNode* myLastNode;
initLinkList(myLastNode);
listNode* myNode;
initLinkList(myNode);
myNode = myList;
while(myNode->nextNode != NULL)
{
myNode = myNode->nextNode;
}
myLastNode->nodeData = myData;
myLastNode->nextNode = NULL;
myNode->nextNode = myLastNode;
myList->nodeData += 1;
}
void reverseList(singleLinkList& myList)
{
if(myList->nodeData > 0)
{
listNode* myNode;
initLinkList(myNode);
myNode = myList->nextNode;
singleLinkList myListA;
initLinkList(myListA);
int i = 1;
while(i <= myList-> nodeData)
{
//借助头插法可以实现链表逆序
addAfterHead(myListA, myNode->nodeData);
myNode = myNode->nextNode;
i += 1;
}
myList = myListA;
free(myNode);
free(myListA);
}
else
{
printf("Your list is empty !!!\n");
return;
}
}
单链表(带头结点)C++面向过程实现
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
相关阅读更多精彩内容
- 前沿:链表是面试中经常问道的知识点,比如链表反转,就地反转,判断单链表是否相交,判断链表是否有环等都是常问的问题....
- 综述 C是一门结构化语言,重点在于数据结构与算法,侧重于对于输入进行运算得到输出(面向过程)。而C++考虑的是构造...
- 一般来说,喜欢站立的人,比喜欢躺着或或坐着的人,身材更好。与躺着的姿势相比,站姿所消耗的能量要多出10%。而单腿站...
- 实验11-2-4 删除单链表偶数节点 (20 分) 1. 题目摘自 https://pintia.cn/probl...