1.单链表创建
单链表的创建有两种,分别是头插法和尾插法,头插法为逆序排序,尾插法为顺序排序,简称“头逆尾顺”。
1.1 头插法
每次插入的新结点均将作为新的第一个数据节点,即后来居上。
创建代码如下,该创建方法将包含头结点:
#include<stdio.h>
#include<stdlib.h>
typedef int ElementType;
typedef struct Lnode{
ElementType data;
struct Lnode *next;
}LNode, *Linklist;
Linklist Create_list_head(Linklist head){ //头插法(含头结点)
head = (Linklist)malloc(sizeof(LNode)); //为头指针开辟内存空间
LNode * node = NULL; //定义工作指针
int count = 0; //定义创建的结点数量
head->next = NULL;
scanf("%d", &count);
for (int i = 0; i < count; i++){
node = (LNode *)malloc(sizeof(LNode)); //创建新结点
node->data = i; //为新结点的数据域赋值
node->next = head->next; //将新结点插入到头结点和第一个结点之间
head->next = node; //更新头结点的next值为新结点
}
return head;
}
1.2 尾插法
每次插入的新结点均将添加到数据的尾部。
创建代码如下,该创建方法将包含头结点:
#include<stdio.h>
#include<stdlib.h>
typedef int ElementType;
typedef struct Lnode{
ElementType data;
struct Lnode *next;
}LNode, *Linklist;
Linklist Create_list_tail(Linklist head){
//尾插法(含头结点)
head = (Linklist)malloc(sizeof(LNode));
Linklist node = NULL;
Linklist end = NULL;
head->next = NULL; //若没有后续结点,则将next值为null
end = head; //若没有后续结点,则记录尾结点为头结点。
int count = 0; //结点个数
scanf("%d", &count);
for (int i = 0; i < count; i++){
node = (LNode *)malloc(sizeof(LNode)); //为新结点开辟空间
node->data = i; //为新的结点数据域赋值
end->next = node; // 将新结点的值给上一个结点的next
end = node; //将新结点标记为尾结点
}
end->next = NULL; //将尾结点的next值赋为NULL
return head;
}
2.单链表的查找
2.1 按序号查找
在带头节点的单链表L中查找序号为i(1<=i<=n)的元素
bool Get_elem_l(Linklist L, int i){
//在带头节点的单链表L中查找序号为i(1<=i<=n)的元素
ElementType e;
LNode * p;
p = L->next;
int j = 1;
while (p && j < i){
p = p->next;
j++;
}
if (!p || j > i) return false;
e = p->data;
printf("元素已经找到,为:%d\n",e);
return true;
}
2.2 按值查找
在带头结点的单链表L中查找序号为i(1<=i<=n)的元素
bool Get_elem_l(Linklist L, int i){
//在带头结点的单链表L中查找序号为i(1<=i<=n)的元素
ElementType e;
LNode * p;
p = L->next;
int j = 1;
while (p && j < i){
p = p->next;
j++;
}
if (!p || j > i) return false;
e = p->data;
printf("元素已经找到,为:%d\n",e);
return true;
}
3.插入元素
在带头结点的单链表中的第i(1<=i<=n)个位置插入数据元素e
bool List_insert(Linklist L, int i, ElementType e){
//在带头结点的单链表中的第i(1<=i<=n)个位置插入数据元素e
LNode * p = L;
int j = 0;
while (p && j < i -1) {
p = p->next;
j++;
}
if (!p || j > i - 1) return false;
LNode * new;
new = (LNode *)malloc(sizeof(LNode));
new->data = e;
new->next = p->next;
p->next = new;
return true;
}
4.删除元素
4.1 按位序删除
在单链表L中删除第i(1<=i<=n)个数据元素
bool List_delete_by_index(Linklist L, int i){
//在单链表L中删除第i(1<=i<=n)个数据元素,此方法未考虑输入参数i大于链表元素个数的情况。
LNode * p = L;
ElementType e;
int j = 0;
while(p && j < i - 1){
p = p->next;
j++;
}
if (!(p->next) || j > i - 1) return false;
LNode * q = p->next;
p->next = q->next;
e = q->data;
printf("删除了位序为%d,其值为%d\n", i, e);
free(q);
return true;
}
4.2 按值删除
在单链表L中删除第1个值为e的数组元素
bool List_delete_by_v(Linklist L, ElementType e){
LNode * p = L, * q = p->next;
while (q != NULL && q->data != e){
p = q;
q = q->next;
}
if (!q) { // 此处若q指针为NULL,则说明找到了末尾仍未找到
printf("删除元素%d不存在!\n", e);
return false;
}
else{
p->next = q->next;
free(q);
printf("删除元素%d成功!\n",e);
return false;
}
}
5.访问链表中的所有元素
输出一个带头结点链表的所有元素的值。
void print_list(Linklist L){
//访问单链表L的所有元素
LNode * p;
p = L->next;
while (p){
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
6.与顺序表的比较
链表相比较于顺序表的主要优势如下:
- 删除指定元素时,无需对元素进行移动;
- 插入指定元素时,无需对元素进行移动。
链表相比较于顺序表的缺点如下:
- 访问某个位置的数据元素,必须要使用到循环;
- 交换元素位置时,较为麻烦。