什么是链表呢,个人理解就是把结构题变量和结构体变量连接在一起所组成的链式结构
由于本人也是刚刚接触链表知识,以防忘记,便想使用此网站记录自己的学习过程。
既然是结构体变量,那我们先定义结构体
struct Node{
int date; //数据域
struct Node* next; //指针域
};
定义出来的结构体就要包含两部分,一部分就是自己要储存的数据,另一部分就是指向下一个节点的地址(也就是指针)
接下来就是要创建一个新的链表了,看我操作
struct Node* creatList()
{ //正下方()
//为强制转换数据类型
struct Node* headNode=(struct Node*)malloc(sizeof(struct Node));
//headNode 为结构体变量
//初始化headNode
//headNode->date=1;
headNode->next=NULL;
return headNode;
}
由于我用的是c语言,所以申请动态地址的时候就用到了malloc函数,你创建的是链表的表头,也可以认为是一个节点,那么创建它就需要的数据类型就需要和指针域的类型一样,记得要让你创建的表头指针域指向NULL,如此我们的表头就创建完成,也就是一个空表。
创建链表,我们也要创建链表的节点原理和上述代码基本一致 代码如下
struct Node* creatNode(int date)
{
struct Node* newNode=(struct Node*)malloc(sizeof(struct Node));
newNode->date=date;
newNode->next=NULL;
return newNode;
}
和上次不同的是,这次我们需要向节点中存入数据,然后再次使指针域指向NULL即可。
接下来就是向创建完成的表中插入节点,插入节点的方法有很多我这里放入两个仅供大家参考
第一个 头插法
void insertNodeByHead(struct Node* headNode,int date)
{
//首先 创建一个想插入的节点
struct Node* newNode=creatNode(date);
//然后使head的指针域数据指向新插入的节点
//并且在连接插入的节点和原来的节点
newNode->next=headNode->next;
headNode->next=newNode;
}
你想要插入节点,就需要利用前文函数先创建一个节点(巧妇难为无米之炊),只需要将创建好的新节点的指针域指表头原来指向的指针域,并且使表头的指针域指向新建的节点,即可完成操作
第二个 在第i个位置插入节点
void insertNodeByi(struct Node* headNode,int i,int date)//插入节点在i位插入
{
struct Node *newNode=creatNode(date);
struct Node *frontNode=headNode;
int j=1;
while(frontNode&&j<i-1)
{
frontNode=frontNode->next;
j++;
}
if(!frontNode||j>i-1) printf("插入出现错误");
newNode->next = frontNode->next;
frontNode->next = newNode;
}
既然想在第i个位置插入那就要找到第i-1这个位置如图
想要找到i-1只需要进行遍历操作,并且计数!!在进行插入操作即可
查找操作也有两种方式
第一种查找第i个元素
struct Node *valueNode(struct Node *headNode,int i)//查找 取第i个元素
{
struct Node *moveNode=headNode->next;
int j=1;//计数
while(moveNode&&j<i)
{
moveNode=moveNode->next;
j++;
}
if(!moveNode||j>i) printf("错误");
printf("您想要取的元素是:%d \n",moveNode->date);
}
首先就要创建一个不属于表中的第三方节点,用来记录和遍历,要想程序进行,首先就要保证第三方不能为NULL,否则表就是空表,无法查找!
第二种 在表中查找想要的元素
struct Node *value1Node(struct Node *headNode,int date)// 查找 查找想要的元素
{
struct Node *moveNode=headNode->next;
int j=1;
while(moveNode&&moveNode->date!=date)
{
moveNode=moveNode->next;
j++;
}
if(moveNode) printf("找到想要的数据在链表的第%d位\n",j);
else printf("未找到或发生错误\n");
}
两者代码几乎一致,不同点就是while循环中的循环条件
删除列表中指定的数据
void deleteNodeByAppoin(struct Node* headNode,int posDate)
{
struct Node* posNode = headNode->next;
struct Node* posNodeFront = headNode;
if(posNode==NULL)
printf("链表空,无法删除!");
else
{
while(posNode->date!=posDate)
{
posNodeFront=posNode;
posNode=posNodeFront->next;
if(posNode==NULL)
{
printf("未找到指定位置,无法删除!");
return;//结束函数
}
}
posNodeFront->next=posNode->next;
free(posNode);
}
}
注意 这种写法仅可以删除第一个想要删除的数据,如果表中还有相同数据,代码需要更改!!!
链表的表长 废话少说代码奉上
struct Node *lenList(struct Node *headNode)//求链表的表长
{
int i=0;
struct Node *moveNode=headNode->next;
while(moveNode)
{
i++;
moveNode=moveNode->next;
}
printf("链表的表长是:%d \n",i);
}
循环条件就是moveNode的地址不为NULL,也就是当到达表尾之后停止,即可完成计数,也就是表长。
啥事都有第一次
本人也是第一次记录有关链表的知识,上述所以观点仅代表个人的意见