人生如棋,我愿为卒,行走虽慢,可有谁见我后退一步?
目录
单链表
链表是线性表的链式存储方式。逻辑上相邻的数据在计算机内的存储位置中不一定相邻。链式存储:通过指针串起来。
单链表的存储方式
链式结构中,除了要存储数据元素外,还要存储它的后继元素(下一个结点)的地址。我们把存储数据元素的信息的域称数据域,存储它的后继元素(下一个结点)位置的域称为指针域。这两部分信息组成数据元素的a[i]的存储映像,称为结点(Node)。因此指针都指向下一个结点,都朝一个方向的,这样的链表称为单链表。单链表的存储方式如下图所示:
对于线性表来说,有头有尾,链表也不意外,为了操作方便,还会给链表增加一个不存放数据的头节点(也可以存放表长等信息,整个链表的存取就必须从头指针开始,我们只要牵住头指针就相当于牵住了整个单链表。注头节点不算真节点,辅助用 那么最后一个结点的位置指向哪里呢?最后一个结点的后继不存在所以我们规定链表的最后一个结点指针为NULL(空)。NULL在链表中往往作为链表结束的判断标志如下图。
单链表的节点结构体定义
#ifndef LIST_H
#define LIST_H
typedef int data_t; //为int取个名字叫data_t
typedef struct node
{
data_t data; //数据域
struct node *next;//指针域,保存下一个结点的地址> 。
}NODE;//用typwdef将结构体等价于类型名NODE
假设p是指向链表第i个元素的指针,则该结点a[i]的数据域我们可以表示为a->data。a[i]的指针域可以表示为p->next,p->next 指向a[i+1]的地址(指针)那么a[i+1]的数据域可以表示为p->next->data.
单链表的基本操作
//1.创建头结点 NODE *create_list(void);
//2.判空, 1为空 int empty_list(NODE *head);
//3.求链表长度 int length_list(NODE *head);
//4.按位置插入结点,需要传三个即头结点、要插入的位置> ,要插入的值 int insrert_listpos(NODE *head, int pos,data_t data);
//5.按位置删除链表,需要传递头结点和删除的位置 int delete_linklistpos(NODE *head,int pos);
//6.安置查找,返回地址.所以我们要遍历整个结点 NODE *find_listdata(NODE *head,data_t data);
//7.安置删除链表结点 int delete_listpos(NODE *head, data_t data);
//8.按位置查找,返回地址 NODE *findlistpos(NODE *head, int pos);
//9.按值修改链表 int update_listdata(NODE *head,data_t old_data,data_t, new_data);
//1o.清空链表,即链表只剩头结点 void clear_list(NODE *head);
//11.销毁链表 void destory_list(NODE **head);
//12.链表的输出 void printf_list(NODE *head);
1.创建头结点
//1.创建头结点
NODE *create_list(void)
{
NODE *head = (NODE*)malloc(sizeof(NODE));//利用malloc函数为头结点申请空间,一个结点包含数据域和指针域。
if(NULL == head)//判断头结点的空间是否申请成功。
{
return NULL;
}
head->data = -1;//头结点的数据初始化,无意义。
head->next = NULL;//头结点的数据初始化,无意义.
return head;
}
2.判空
//2.判空, 1为空
int empty_list(NODE *head)
{
if(NULL != head)//判断头结点是否申请成功
{
return ((head->next==NULL) ? 1 : 0);//如果头结点的指针域是空则返回1,反之返回0;
}
else
return -1;//异常
}
3.求链表长度
//3.求链表长度
int length_list(NODE *head)
{
if(NULL == head)
{
return -1;
}
int len = 0;//定义变量len,累加求长度。
NODE *p = head->next;//定义一个结构体指针p,指向头结点下一个结点(有效结点)
while(p != NULL)