链表是一种常见的数据结构,与数组在表现形式上很相似,其无空间限制,可以存放很多数据,同样避免了空间浪费,这些都是数组所没有的优点,但也有一个最大的缺点,就是不便于数据访问。链表操作包括数据插入、数据删除、头插、头删、尾插、尾删、销毁等。接下来就用图解的方式来届时链表的操作:
链表形式:
链表有很多节点形象的依次连接在一起,每个节点都由一个数据域和指针域构成,指针域存放着下一个节点的地址,故而形象的使各个节点依次相连。链表尾的指针域要置空,以免会出现不必要的差错,同样也便于链表遍历。
插入一个节点:
1节点的指针域原本指向的是2节点,在1节点处插入一个节点,原来的2节点变为了3节点,插入的节点变为了2节点,1节点的指针域原本存放着3(原2节点)节点的地址,现在重新赋值,变成存放着2(新插入的节点)节点的地址,而2(新插入的节点)节点的指针域存放着3(原2节点)节点的地址。
删除一个节点
例如删除2节点,只需将原3(现2节点)节点的地址赋给1节点的指针域中,再将原2(即删除的节点)节点的指针域释放掉即可
头插:
1节点原本是之前的0节点,也就是链表头,现在插入一个链表头进来,原链表头就变为了1节点,新插入的节点就变成了链表头,此操作只需把1(原链表头)节点的地址赋给0(现链表头)节点。
头删:
头删的操作更为简单,直接把链表头释放掉即可,再将原来的1节点在设置为链表头即可,再次就不画图了。
具体代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct ListNode
{
int data;
struct ListNode* next;
}ListNode;
typedef struct List
{
ListNode* head;
}List;
ListNode* ListInit() //开辟一个空间
{
return malloc(sizeof(ListNode));
}
void insert_list(ListNode* head, int n, int data) //插入一个节点
{
ListNode* tem;
for (tem = head;tem&&n--; tem = tem->next);//找到要插入数据的位置
ListNode* new_data =ListInit();
new_data->data =data;
new_data->next =tem->next;//tem->next中存放的是下一个数据的地址,将这个地址赋给
new_data的指针域
tem->next =new_data;//使tem->next指向new_data
}
void print(ListNode* head) //打印
{
ListNode* tem;
if (head == NULL)
{
printf("\n该链表不存在\n");
return;
}
for (tem = head; tem;tem = tem->next)
{
printf("%d ", tem->data);
}
printf("\n");
}
void del_list(ListNode*head, int n) //删除
{
ListNode* tem;
for (tem = head;tem&&n--; tem = tem->next);//找到要删除这个数据的上一个数据的位置
struct list *tmp =tem->next;//将这个要删除的数据赋给tmp
tem->next =tem->next->next;//将这个要删除的数据的next中存放的地址赋给该数据的上一个位置
free(tmp);
}
void insert_front(ListNode** head, int data)
//头插法
{
ListNode* tem =ListInit();
tem->data = data;//赋值数据
tem->next =*head;//在tem的指针域中存放之前的链表头
*head = tem;//使tem成为新的链表头
}
void del_front(ListNode** head) //头删
{
ListNode* tmp =(*head)->next;//将链表头的指针域中存放的下一个节点的地址赋给tmp
free(*head);//释放链表头
*head = tmp;//使tmp成为新的链表头
}
void insert_after(ListNode* head, int data) //尾插
{
ListNode* tem;
int n = 0;
for (tem = head; tem;tem = tem->next)
{
n++;
}
insert_list(head, n -1, data);
}
void del_after(ListNode *head) //尾删
{
ListNode* tem;
int n = 0, b;
for (tem = head; tem;tem = tem->next)
{
n++;
}
b = n - 2;
for (tem = head;tem&&b--; tem = tem->next);
free(tem->next->next);
tem->next = NULL;
}
void destory(ListNode *head) //销毁链表
{
ListNode* tem;
int n = 0, b;
for (tem = head; tem;tem = tem->next)//链表遍历
{
n++;//统计节点数
}
b = n - 1;
while ((head->next)&& b--)
{
del_list(head,b);//依次删除链表头
}
free(head);//释放最后一个链表头
}
int main()
{
ListNode* first =ListInit();
first->next = NULL;
first->data = 1;
insert_list(first, 0,7);
insert_list(first, 0,4);
insert_list(first, 2,4);
insert_list(first, 2,13);
insert_list(first, 3,11);
insert_front(&first,9);
insert_list(first, 6,0);
//del_front(&first);
//del_list(first, 0);
insert_after(first,6);
del_after(first);
del_front(&first);
print(first);
del_front(&first);
print(first);
destory(first);
first = NULL;
print(first);
system("pause");
return 0;
}