单链表默认的结构体
typedef struct LNode{
int data;
struct Node *next;
}LNode;
1.分别采用头插法和尾插法建立一个带头结点的单链表
LNode* tail_insert()
{
int x;
scanf("%d",&x);
LNode* L=(LNode*)malloc(sizeof(LNode));
LNode* r=L;
while(x!=99999)
{
LNode* s=(LNode*)malloc(sizeof(LNode));
s->data=x;
s->next=NULL;
r->next=s;
r=s;//r=r->next;
scanf("%d",&x);
}
return L;
}
思想:
先设置变量存储数据。
建立L头节点,将头节点赋于r用来遍历。
当x不是9999时循环一直继续,可以一直进行插入。
动态存储一个s节点,将x保存到s data因为尾插所以s后面为NULL。
前面指针还未指向,L和s中间指针仍然需要指向,要因为我们用r存储了L所以直接将r指针指向后面的s就行。同时不断更新r的位置(将s的位置赋于r,相当于每次r在s之前)从而能够实现指针的指向。
尾插法
LNode* head_create()
{
LNode*L=(LNode*)malloc(sizeof(LNode));
L->next=NULL;
int x;
scanf("%d",&x);
while(x!=9999)
{
LNode*s=(LNode*)malloc(sizeof(LNode));
s->data=x;
s->next=L->next;
L->next=s;
scanf("%d",&x);
}
return L;
}
思想:
建立头节点
输入x当为9999时停止循环
建立节点,将数据赋值给s。
插入节点相当于插入到L和L后一个节点中间。我们需要将L指向新的节点,新的节点指向L后的那个第一个节点。
2.一个带头结点的链表,申请一个值为x的空间,插入L仍然递增有序
LNode* insert_x(LNode*&L,int x)
{
LNode *s=L;
while(s->next!=NULL)
{
if(s->next->data>x)
{
LNode*p=(LNode*)malloc(sizeof(LNode));
p->data=x;
LNode*r=s->next;
p->next=r;
s->next=p;
}
s=s->next;
}
}
思想:
进行循环若s下一个不为空则还有数据。
判断s中每个与x大小,找到第一个比x大的数据。(用s->next原因,因为s一开始是头指针不保存数据)
找到之后,我们建立新节点,将新节点插入到这两之间。
可知s->next为我们找到那个指针,s就是前面的因而我们也可以直接写(p->next=s->next;s->next=p;)也可以。
若为找到s继续往后。
3.删除单链表第一个为x元素
void del_x(LNode*&L,int x)
{
LNode* p=L;
while(p->next!=NULL)
{
if(p->next->data==x)
{
LNode*r=p->next;
p->next=r->next;
free(r);
break;
}
p=p->next;
}
}
思想:
建立节点从开始往后遍历,若不为x继续遍历,若为x则进行指针删除并且中止
由于p->next数据是x,我们只需将p指向p->next->next并且释放p->next即可,我这里用了r去替换p->next是一样的。
4.删除所有x的元素
void del_x(LNode*&L)
{
LNode*p=L;
while(p->next!=NULL)
{
if(p->next->data==x)
{
Lode* r=p->next;
p->next=r->next;
free(r);
}
p=p->next;
}
}
思想:
同3只是不用中止。
5.带头结点链表就位逆置
void reverse(LNode*&L)
{
LNode*p=L->next;
L->next=NULL;
while(p!=NULL)
{
r=p->next;
p->next=L->next;
L->next=p;
p=r;
}
}
思想:
相当于新建一个头节点为L,L的下一个为NULL。由此可见我们将会对L->next进行修改,我们需要将其先进性保存。
当不为空循环(为什么不是p->next,因为我们用了r保存了p->next,在最后一步时已经时p->next了,所以用p即可)。
同理我们后面也对p->next修改了因而要提前进行保存。后续相当于头插。
6.删除最小的元素
bool del_min(LNode*&L)
{
LNode* s=L,*pose=L;
while(s->next!=NULL)
{
if(s->next->data<pose->next->data)
{
pose=s;
}
s=s->next;
}
LNode *r=pose->next;
pose->next=r->next;
free(r);
}
思想:
设置两个变量一个pose另一个s
pose用来保存最小元素的前一个位置。
若s下一个不为空则继续遍历,如果s比pose小将s赋值给pose
最后将pose->next即最小元素删除。将pose->next前后两个指针相连。
7.按照递增有序输出所有点并释放空间
void print_elem(LNode*&L)
{
LNode*pose=L,*s=L;
while(L->next!=NULL)
{
while(s->next!=NULL)
{
if(s->next->data<pose->next->data)
{
pose=s;
}
s=s->next;
}
LNode*r=pose->next;
pose->next=r->next;
printf("%d\n",r->data);
free(r);
}
}
思想:
不断地查找最小值,因而最外环中止即头节点下一个是否为空,这时所有元素全部释放了。
在同6不断释放最小元素,记得打印即可。
8.将一个带头结点单链表最小元素移动到最前面
void move_min(LNode*&L)
{
LNode*pose=L,*s=L;
while(s->next!=NULL)
{
if(s->next->data<pose->next->data)
{pose=s;}
s=s->next;
}
LNode*r=pose->next;
pose->next=r->next;
r->next=L->next;
L->next=r;
}
思想:
先找到最小的元素不用将其释放,将最小元素前指针和后指针连在一起。
最后将这个节点头插到头节点和第一个元素之间。
9.设有一个无序的链表编写以下功能1.找出最小值2.若为奇数则与后继点交换3.偶数则删除后继节点
void func(LNode*&L)
{
LNode*pose=L,*s=L;
while(s->next!=NULL)
{
if(s->next->data<pose->next->data)
{
pose=s;
}
s=s->next;
}
LNode*u=pose->next;
LNode*r=r->next;
u->next=r->next;
if(u->data%2==0)
{
free(u);
}
else
{
r->next=pose->next;
pose->next=u->next;
}
}
思想:
先找到最小值,然后进行判断奇数偶数
不管插入还是交换次序,我们都可以先将pose->next位置和他next的next进行两个指针相连。
若为偶数直接free释放
交换次序将pose->next赋于r->nex,将r指向pose后一个节点
在连接前面节点把u->next(相当于r)赋给pose->next