链表
链表可以动态的进行存储分配,也就是说,链表是一个功能极为强大的数组,他可以在节点中定义多种数据类型,还可以根据需要随意增添,删除,插入节点。
链表都有头指针,一般为heae,存放的是一个地址。链表节点分为两类,头节点和一般节点,头节点是没有数据域的。链表的每个节点都分为两部分,一个数据域,一个指针域。
以上内容摘自:https://www.cnblogs.com/ariel-dreamland/p/10469696.html
若线性表为空表,则头节点的指针域为空。
链表分为:单链表、循环链表、双向链表。
循环链表的最后一个结点的指针是指向该循环链表的第一个结点或者表头结点,从而构成一个环形的链;
双向链表是每个节点包括两个指针域,分别指向前一个节点和后一个节点。
链表部分代码解释:
链表一般用结构体定义:
typedef struct node{
ElemType data;
struct node *next;
} LinkList;
一般创建链表我们都用typedef struct,因为这样定义结构体变量时,就可以直接用LinkList *a; 定义结构体变量了。
typedef:给变量一个易记且意义明确的新名字;另一作用是简化一些比较复杂的类型声明。
typedef struct node{
ElemType data;
struct node *next;
} LinkList;
以上代码体现了第一个作用,该语句实际上完成了连个操作:
1)定义了一个新的结构类型
typedef struct node{
ElemType data;
struct node *next;
} ;
2)typedef 为这个新的结构起了一个名字,LinkList.
假设p是指向线性表第i个元素的指针,则该节点的数据域可以用p->data来表示,是一个数据元素;节点的指针域可以用p->next来表示,p->next的值是一个指针。
初始化一个链表,n为链表节点个数:
LinkList *creat(int n){
LinkList *head,*node,*end;//定义头节点,普通节点,尾部节点
head = (LinkList*)malloc(sizeof(LinkList));//头节点分配内存
end = head; //刚开始将尾部节点指向头节点
for(int i = 0;i < n;i++)
{ //尾插法
node=(LinkList*)malloc(sizeof(LinkList));
cin>>node->data>>endl;
end->next = node;
end = node;
}
end->next = null;//结束创建
}
//修改链表节点的值
void change(LinkList *list, int n){ //假设要修改第n个节点的值
LinkList *t = list;
int i = 0;
//先找到第n个节点
while(i<n && t !=NULL){
t = t->next;
i++;
}
if(t != NULL){
cout<<"输入要修改的值"<<endl;
cin>>&t->data<<endl;
}
else
cout<<"节点不存在"<<endl;
}
//插入链表节点
void insert(LinkList *list, int e, int n){ //在第i个节点前插入元素n,list的长度加1
int j; //负则找到第i个元素
LinkList p,s;
p = *list;
//此时P指向链表的头节点
/**
最初创建链表的时候那个LinkList *list是创建整个链表,一般除了创建那里,其他的都表示指向头节点或第一个节点;
这个list节点有头节点,所以p = *list; 表示p 指向头节点;若链表没有头节点,表示指向第一个节点。
*/
j = 1;
while(p && j<i){ //寻找第i个元素
p = p->next;
++j;
}
if( !p || j>i) return ERROR; //第i个元素不存在
s = (LinkList)malloc(sizeof(Node)); //生成新节点
s->data = n;
s->next = p->next;
p->next = s;
return OK;
}
以上内容大多来自于博客:https://www.cnblogs.com/ariel-dreamland/p/10469696.html