简介
链表是一种非常常见的数据结构,主要用来对复杂的数据集进行数据的增删改查,其优点也是插入删除速度快;内存利用率高,不会浪费内存
;大小没有固定,拓展很灵活。
单链表代码实现
#include <stdio.h>
#include <stdlib.h>
typedef int ElemType;
struct node
{
ElemType data;
struct node *next;
};
/*
根据用户的输入,
创建一个单链表
*/
struct node *create_list()
{
int d;
struct node *first = NULL; //指向链表的第一个结点
struct node *last = NULL;//指向链表的最后一个结点
struct node *p = NULL;// 指向新创建的结点
while (1)
{
scanf("%d", &d);
if (d == 0)
{
break;
}
/*
step 1: 创建一个新结点,保存数据
*/
p = malloc(sizeof(*p));
p->data = d;
p->next = NULL;
/*
step 2: 把新创建的结点,加入到链表中去
*/
if (first == NULL)
{
first = p;
last = p;
}
else
{
//"尾插法"
last->next = p;
last = p;
//"头插法"
//p->next = first;
//first = p;
#if 0
/*建立一个有序链表(升序)*/
struct node *r = NULL; //指向链表中第一个比p->data大的结点
struct node *pre = NULL;//指向链表中r前面那个结点
/*
2.1 在链表中找到第一个值比p->data
大的结点,代码如下:
*/
r = first;
while (r)
{
if (r->data > p->data) //r找到啦
{
break;
}
pre = r;
r = r->next;
}
/*
2.2
*/
if (r == NULL) //现有链表中所有结点的值都比p->data要小
{
//P应该是插入到最后,
last->next = p;
last = p;
}
else
{
if (r == first)
{
//p应该插入到最前面
p->next = first;
first = p;
}
else
{
p->next = r;
pre->next = p;
}
}
#endif
}
}
return first;
}
/*
在链表h中,元素值为k的那个结点的后面,
增加一个新结点,新结点的数据值为x.
如果有多个k,则在第一个k后面插入,
如果没有k,则在末尾插入.
再把新链表的第一个结点的指针返回。
*/
struct node* insert(struct node *h, int k, int x)
{
struct node *p = h;
struct node *pre = NULL;//指向p前面那个结点
struct node *pnew = malloc(sizeof(*pnew));
pnew->data = x;
pnew->next = NULL;
/*
step 1: 找插入位置
*/
while (p)
{
if (p->data == k)
{
break;
}
pre = p;
p = p->next;
}
/*
step 2:插入
*/
if (p)
{
pnew->next = p->next;
p->next = pnew;
}
else
{
pre->next = pnew;
}
return h;
}
/*
在链表h中,元素值为k的那个结点前面
新增一个结点,其元素值为x.
如果有多个k值,则在第一个k前面插入,
如果没有k,则在最后面插入。
把新链表的第一个结点的指针返回.
*/
struct node* insert_v2(struct node *h, int k, int x)
{
struct node *p = NULL; //指向第一个k
struct node *pre = NULL;//指向p前面那个结点
struct node *pnew = malloc(sizeof(*pnew));
pnew->data = x;
pnew->next = NULL;
if (h == NULL)
{
return pnew;
}
/*
step 1: 找插入位置
*/
p = h;
while (p)
{
if (p->data == k)
{
//呵呵,终于找到你啦
break;
}
pre = p;
p = p->next;
}
/*
step 2: 插入操作
*/
if (p) //找到p啦
{
if (p == h)//p是第一个结点
{
pnew->next = p;
h = pnew;
}
else
{
pnew->next = p;
pre->next = pnew;
}
}
else
{
pre->next = pnew;
}
return h;
}
/*
delete_node:在链表h中,删除
一个值为x的结点.
返回删除后的第一个结点
*/
struct node *delete_node(struct node *h, int x)
{
struct node *first = h; //指向链表的第一个结点
struct node *px = NULL; //指向要删除的那个结点
struct node *pre = NULL;//指向px前面那个结点
/*
step 1: 找到要删除的那个结点,
以及它前面那个结点
*/
px = first;
while (px)
{
if (px->data == x)
{
break;
}
pre = px;//
px = px->next;
}
/*
step 2: 删除
*/
if (px == NULL) //没有您要删除的结点
{
return first;
}
if (px == first) //要删除的那个结点是第一个结点
{
first = first->next;
px->next = NULL;
free(px);
return first;
}
else
{
pre->next = px->next;
px->next = NULL;
free(px);
return first;
}
}
struct node *delete_all_x(struct node *h, int x)
{
struct node *first = h; //指向链表的第一个结点
struct node *px = first; //指向要删除的那个结点
struct node *pre = NULL;//指向px前面那个结点
while (1)
{
/*
step 1: 找到要删除的那个结点,
以及它前面那个结点
*/
//px = first;
while (px)
{
if (px->data == x)
{
break;
}
pre = px;//
px = px->next;
}
/*
step 2: 删除
*/
if (px == NULL)
{
return first;
}
if (px == first) //要删除的那个结点是第一个结点
{
first = first->next;
px->next = NULL;
free(px);
px = first; //下一个开始查找的位置
}
else
{
pre->next = px->next;
px->next = NULL;
free(px);
px = pre->next; //下一个开始查找的位置
}
}
}
/*
遍历链表
*/
void print_list(struct node *p)
{
while (p)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
int main()
{
struct node *h = create_list();
print_list(h);
//int k,x;
//scanf("%d%d", &k,&x);
//h = insert(h, k, x);
//h = insert_v2(h, k, x);
//print_list(h);
int x;
scanf("%d", &x);
h = delete_all_x(h, x);
print_list(h);
return 0;
}