单链表的相关操作和测试(C语言)
“single-LinkList.h” 头文件
#ifndef _SINGLE_LL
#define _SINGLE_LL
#include<stdlib.h>
#include<stdio.h>
#define flag -100
typedef int dataType;
//单链表的结点
typedef struct lnode{
dataType data;
struct lnode *next;
}Lnode,*LinkList;
1.创建带头结点的单链表(从表头插入)
//创建带头结点的单链表
LinkList Creat_LinkList1( ){ //从表头插入结点(带有头结点)
LinkList L;
Lnode *s;
int x;
L=(Lnode*)malloc(sizeof(Lnode)); //创建头结点
L->next=NULL; //初始化最后一个结点的指针域为NULL
scanf("%d",&x);
while(x!=flag)
{
s=(Lnode*)malloc(sizeof(Lnode));
s->data=x; s->next=L->next;
L->next=s;
scanf("%d",&x);
}
return L;
}
2.创建带头结点的单链表(从表尾插入)
注意:用一个R指针指向当前链表的最后一个结点
//创建带头结点的单链表
LinkList Creat_LinkList2( ){ //从表尾插入结点(带有头结点)
LinkList L;
Lnode *s,*R;
int x;
L=(Lnode*)malloc(sizeof(Lnode));
L->next=NULL; R=L; //R指向了当前链表的最后一个结点
scanf("%d",&x);
while(flag!=x)
{
s=(Lnode*)malloc(sizeof(Lnode));
s->data=x;
R->next=s; R=s;
scanf("%d",&x);
}
R->next=NULL; //置表尾结点next指针为空
return L;
}
3.求表的长度
//求表长度
int Length_LinkList(LinkList L){
int l=0;
Lnode *p=L;
if(p->next) //判定后继结点是否存在,有则l+1
{
p=p->next;
l++;
}
return l;
}
4.按序号查找元素结点
//按序号查找元素结点
Lnode* Get_LinkList(LinkList L,int i){
int j=0;
Lnode *p=L;
if(i<0)
{
printf("序号值非法,查找失败!\n");
return NULL;
}
while(p->next && j<i)
{
p=p->next;
j++;
}
if(j==i)return p; //判别是否查找到该结点
else NULL;
}
5.按值查找(定位)
//按值查找(定位)
Lnode* Locate_LinkList(LinkList L,dataType x){
Lnode *p=L;
while(p->next && p->data!=x)
p=p->next;
if(p->data==x) return p; //做法和按序号查找相似,判断是否找到了data=x的结点
else return NULL;
}
6.按序号插入结点
//按序号插入结点
int Insert_LinkList( LinkList L,int i,dataType x){
Lnode *p,*s;
p=Get_LinkList(L,i-1);
if(!p)
return 0;
else
{
s=(Lnode*)malloc(sizeof(Lnode));
s->data=x;
s->next=p->next;
p->next=s;
}
return i;
}
7.按序号删除结点
//按序号删除结点
int Delete_LinkList( LinkList L,int i,dataType *x){
Lnode *p,*s;
p=Get_LinkList(L,i-1);
if(!p)
return 0;
else
{
s=p->next;
p->next=p->next->next;
*x=s->data;
free(s);
}
return i;
}
8.释放单链表
执行此操作不能忘了头结点
//释放单链表
int Free_LinkList(LinkList L){
Lnode *p=L->next;
Lnode *s;
free(L);
while(p)
{
s=p;
p=p->next;
free(s);
}
return 10;
}
9.打印链表
//打印链表
int display_LinkList(LinkList L){
Lnode *p=L->next;
if(!p) {
printf("表空\n");
return -1;
}
else
while(p->next)
{
printf("%-3d",p->data);//只能打印到倒数第二个结点
p=p->next;
}
printf("%-3d\n",p->data); //打印表尾结点
return 10;
}
10.翻转链表
注意:在此翻转的操作中要理清思路,需要灵活地从头结点处将一个链表拆分成两个链表
//翻转链表
void reverse(LinkList L){
Lnode *p=L->next,*s;
L->next=NULL; //将头指针置空,成为新的链表的头指针
while(p)
{
s=p; p=p->next;
s->next=L->next;
L->next=s;
}
}
/*
* 注意:在此翻转的操作中要理清思路,需要灵活地从头结点处将一个链表拆分成两个链表
*/
#endif
Mode.cpp
#include"single_LinkList.h"
#include<stdio.h>
int main(){
LinkList L;
int x,f1,f2,f3;
L=Creat_LinkList2(); //创建一个表
if(L!=NULL)
display_LinkList(L);
printf("在第3结点的位置插入元素:78\n");
f1=Insert_LinkList(L,3,78);
if(f1==3)
display_LinkList(L);
printf("删除第8结点\n");
f2=Delete_LinkList(L,8,&x);
if(f2==8)
display_LinkList(L);
f3=Free_LinkList(L);
if(f3>0)
printf("释放链表,结束!");
}
补充
使用p->next 和 p指针作为循环判断依据是,p->next能遍历执行循环体到倒数第二个结点,而p指针可以遍历执行循环体到表尾结点;
【小白上路,第一个CSDN,学习之用哈<--> <-->】