#include<iostream>
using namespace std;
typedef struct LinkNode{
char data;
struct LinkNode* next;
}LNode,*LinkList,*NodePtr;
//定义链表
LinkList initLinkList(){
NodePtr tempHeader=(NodePtr)malloc(sizeof(LNode));
if(tempHeader==NULL)//判断内存是否分配成功
exit(0);//分配失败就退出
tempHeader->data='\0';
tempHeader->next=NULL;
return tempHeader;
}
//初始化链表
void printList(NodePtr paraHeader){
NodePtr p=paraHeader->next;
while(p!=NULL){
printf("%c",p->data);
p=p->next;
}
printf("\r\n");
}
//打印链表
void appendElement(NodePtr paraHeader, char paraChar){
NodePtr p,q;
q=(NodePtr)malloc(sizeof(LNode));
if(q==NULL)
exit(0);
q->data=paraChar;
q->next=NULL;
p=paraHeader;
while(p->next!=NULL){
p=p->next;
}
p->next=q;
}
//尾插法
void insertElement(NodePtr paraHeader, char paraChar, int paraPosition){
NodePtr p,q;
p=paraHeader;
for(int i=0;i<paraPosition;i++){
p=p->next;
if(p==NULL){
printf("The position %d is beyond the scope of the list.", paraPosition);//判断插入位置是否合理
return;
}
}
q=(NodePtr)malloc(sizeof(LNode));
if(q==NULL)
exit(0);
q->data=paraChar;
q->next==NULL;
printf("linking\r\n");
q->next=p->next;
p->next=q;
}
//在第paraPosition位插入数据
void deleteElement(NodePtr paraHeader, char paraChar){
NodePtr p,q;
p=paraHeader;
while((p->next!=NULL)&&(p->next->data!=paraChar)){
p=p->next;
}
if(p->next==NULL){
printf("Cannot delete %c\r\n", paraChar);
return;
}
q=p->next;
p->next=p->next->next;
free(q);//释放结点
}
//按值删除
void appendInsertDeleteTest(){
LinkList tempList=initLinkList();
printList(tempList);
appendElement(tempList, 'H');
appendElement(tempList, 'e');
appendElement(tempList,'l');
appendElement(tempList,'l');
appendElement(tempList,'o');
appendElement(tempList,'!');
printList(tempList);
deleteElement(tempList,'e');
deleteElement(tempList,'a');
deleteElement(tempList,'o');
printList(tempList);
insertElement(tempList,'o',1);
printList(tempList);
}
void basicAddressTest(){
LNode tempNode1,tempNode2;
tempNode1.data=4;
tempNode1.next=NULL;
tempNode2.data=6;
tempNode2.next=NULL;
printf("The first node: %ld, %ld, %ld\r\n",&tempNode1,&tempNode1.data,&tempNode1.next);
printf("The second node: %ld, %ld, %ld\r\n",&tempNode2,&tempNode2.data,&tempNode2.next);
tempNode1.next=&tempNode2;
}
//打印地址
int main(){
appendInsertDeleteTest();
basicAddressTest();
return 0;
}
运行结果:
链表中的重要算法:
尾插法示意图:
插入算法:
删除算法:
学习心得:
-
链表的基本操作: 链表是一种常见的数据结构,它由一系列节点组成,每个节点包含数据和指向下一个节点的指针。在这段代码中,作者实现了链表的初始化、打印、尾部插入、按位置插入和按值删除等基本操作,这些操作是链表常见的基本操作,对于理解链表的工作原理和使用方法非常重要。
-
内存分配与释放: 作者使用了动态内存分配函数
malloc()
来为链表节点分配内存空间,并在适当的时候使用free()
函数释放节点所占用的内存空间。动态内存分配可以让程序在运行时动态地分配内存空间,从而灵活地管理内存资源,但同时也需要注意及时释放已分配的内存空间,以避免内存泄漏问题。 -
指针的使用: 在链表的实现过程中,作者频繁地使用了指针来操作节点之间的关系。指针是C++中非常重要的概念,它可以指向内存中的某个地址,并通过对指针的操作来间接地操作所指向的数据。通过这段代码的练习,我更加熟悉了指针的使用方法,包括指针的声明、指针的赋值、指针的解引用等操作。
-
错误处理: 在代码中,作者通过一些条件判断语句来处理一些可能出现的错误情况,如内存分配失败时的处理、插入位置越界时的处理等。良好的错误处理机制可以增强程序的健壮性和可靠性,减少程序出错的可能性,提高程序的稳定性。
总的来说,通过编写这段代码并理解其中的各种操作,我对链表的原理和使用方法有了更深入的理解,并且加深了对指针的掌握。这对我后续学习和应用其他数据结构和算法也会有很大的帮助。