首先,让我们回顾一下顺序表的优缺点:
1、优点:
随机存取;
存储空间利用率高。
2、缺点:
插入、删除效率低;
必须按事先估计的最大元素个数分配连续的存储空间,难以临时扩大。
采用链式存储结构的线性表称为链表。
链表有单链表、循环链表和双向链表等多种类型。
链表中,不仅需要存储每个数据元素,还需存储其直接后继的存储地址,这两部分数据信息组
合起来称为结点。
结点包括两类域:
存储数据元素信息的域称为数据域;
存储直接后继存储地址的域称为指针域。
每个结点只包含一个指针域的链表,称为单链表。
最后一个结点的指针域为NULL,在图中记为^。
first是头指针,指向链表中的第一个结点,链表中的第一个结点称为头结点
目录
头文件及函数声明等:
菜单函数:
初始化链表:
显示元素:
添加元素:
编辑
插入元素:
编辑
删除元素:
编辑
查找元素:
修改元素:
元素排序:
元素备份:
主函数:
头文件及函数声明等:
#include //提供system()
#include //提供malloc()和free()
#include //开辟空间
#include //提供strcpy()等
typedef int ElemType;
typedef struct node;
typedef int Startus;//获得元素的操作
//结点结构体
typedef struct node
{
ElemType element ; //结点的数据域
struct node *link; //结点的指针域(指向节点的指针)
}Node;
//头结点结构体
typedef struct singleList
{
struct node * first;//头结点
int n;
}SingleList;
SingleList slist;//结构体变量
void menu( );
void init(SingleList *L);
void add(SingleList *L);
void display(SingleList *L);
void del(SingleList * L,int i);
Node * find(SingleList * L,int i);
void insert(SingleList *L,int i);
int change(SingleList *L,int x,int y);
void bubbleSort(SingleList *L);
void save(SingleList *L);
菜单函数:
//定义系统菜单√
void menu( )
{
int op,i,x,y;
printf("==================================\n");
printf("------单链表的基本操作 V1.6-----\n");
printf("0. 初始化单链表√ \n");
printf("1. 添加元素√ \n");
printf("2. 插入元素√ \n");
printf("3. 删除元素√ \n");
printf("4. 修改元素 \n");
printf("5. 查找元素√ \n");
printf("6. 升序排序元素 \n");
printf("7. 备份顺序表 \n");
printf("8. 结束操作√ \n");
printf("9. 显示操作√ \n");
printf("==================================\n");
printf("请选择操作的菜单项:");
scanf("%d",&op);
switch(op){
case 0:
init(&slist);
break;
case 1:
add(&slist);
break;
case 2:
printf("请输入要插入的位置:");
scanf("%d",&i);
insert(&slist,i);
break;
case 3:
printf("请输入你要删除的元素的位置:");
scanf("%d",&i);
del(&slist,i);
break;
case 4:
printf("\n===========【修改元素】===============\n");
printf("请输入要修改的元素的值:");
scanf("%d",&x);
printf("请输入修改后的元素的值:");
scanf("%d",&y);
if(change(&slist,x,y))
{
printf("恭喜,修改成功!\n");
}
else
{
printf("对不起,修改失败!\n");
}
break;
case 5:
printf("\n===========【查找元素】===============\n");
printf("请输入要查找的元素:");
scanf("%d",&i);
find(&slist,i);
break;
case 6:
bubbleSort(&slist);
break;
case 7:
save(&slist);
break;
case 8:
exit(0); //结束操作
break;
case 9:
display(&slist);
break;
default:
printf("你选择的菜单项不存在,请重新选择!\n");
break;
}
system("pause");
system("cls");
}
效果如下:
初始化链表:
//初始化单链表√
void init(SingleList *L)
{
printf("\n==========【初始化单链表】==============\n");
L->first=NULL;
L->n=0;
printf("顺序表初始化成功!\n");
system("pause");
system("cls");
}
效果如下:
显示元素:
//显示元素√
void display(SingleList *L)
{
Node *p;
printf("\n===========【显示元素】===============\n");
if(L->n==0)
printf("此单链表为空表,无法输出元素!\n");
p=L->first;
printf("该单链表中所有元素如下:");
while(p)
{
printf("%-4d",p->element);
p=p->link;
}
system("pause");
system("cls");
}
效果如下:
添加元素:
//添加元素√
void add(SingleList *L)
{
int i,m,x;
Node *q,*last; //last永远指向最后一个结点
last=L->first;//在未创建结点时,last没有值
printf("\n===========【添加元素】===============\n");
printf("请输入要添加的元素个数:");
scanf("%d",&m);
for(i=1;i<=m;i++)
{
printf("请输入第%d个元素的值:",i);
scanf("%d",&x);
q=(Node *)malloc(sizeof(Node));//为新结点开辟新内存
q->element=x; //新结点的数据域赋值
//q->link=NULL;
if(last==NULL)//判断是否是空表
{
L->first=q;
last=q;
}
else
{
//尾插法深刻理解:
last->link=q; //第一步
last=q; //第二步
}
L->n++;
}
printf("元素添加成功!\n");
system("pause");
system("cls");
}
插入元素:
//插入元素√
void insert(SingleList *L,int i)
{
Node *p,*q;
int x,j;
printf("\n===========【插入元素】===============\n");
printf("请输入要插入的新结点数据域:");
scanf("%d",&x);
if (i<0||i>L->n)
{
printf("越界!\n");
}
p=L->first;
for ( j=0;jlink; //从头结点开始查找ai
}
q=(Node *)malloc(sizeof(Node));//为新结点开辟新内存
q->element=x; //新结点的数据域赋值
if(i>0)
{
q->link=p->link; //新结点插在单链表中间位置的情况
p->link=q;
}
else
{
q->link=L->first; //新结点插在a0之前,成为新的头结点
L->first=q;
}
L->n++; //表长增加1
printf("插入成功!\n");
}
删除元素:
//删除元素√
void del(SingleList * L,int i)
{
int j;
Node *p,*q;
printf("\n===========【删除元素】===============\n");
if(!L->n)
printf("该单链表为空!!\n");
if(i<1||i>L->n)
printf("没有该元素!!\n");
q=L->first;
p=L->first;
for(j=0;jlink;
if(i==1)
{
L->first=L->first->link; //删除头节点
}
else
{
p=q->link; //p指向ai
q->link=p->link;//从单链表中删除P所指向的结点
}
free(p);//释放空间
L->n--; //长度减一
printf("删除成功!\n");
}
查找元素:
//查找元素√
Node * find(SingleList * L,int x)
{
Node *p,*q=NULL;//p用来追踪每个结点,q用来保存查找到的元素的地址
printf("\n===========【查找元素】===============\n");
if(L->n==0)
{
q=NULL;
printf("该表为空表!\n");
}
p=L->first;
while(p)
{
if(p->element==x)
{
q=p;
break;
}
p=p->link; //p往后移动
}
printf("恭喜,成功查找到值为%d的元素!\n",x);
}
修改元素:
//修改元素
int change(SingleList *L,int x,int y)
{
Node *t=find(L,x);
printf("\n===========【修改元素】===============\n");
if(t!=NULL)
{
t->element=y;
return 1;
}
else
{
return 0;
}
}
元素排序:
//元素排序√
void bubbleSort(SingleList *L)
{
int i,j,t; //t是临时变量
Node * p, *q;
p=L->first;
q=p->link;
printf("\n===========【元素排序】===============\n");
if(p==NULL||q==NULL)
{
printf("该链表为空!\n");
}
else
{
for(i=0;in -1;i++)//比较的躺数
{
for(j=0;q!=NULL;j++)//比较的次数
{
if(p->element > q->element)
{
t=p->element;
p->element=q->element;
q->element=t;
}
p=p->link;
q=q->link;
}
p=L->first;
q=p->link;
}
printf("排序成功!\n");
}
}
元素备份:
//元素备份√
void save(SingleList *L)
{
int i;
Node *q=L->first;
FILE *fp;
printf("\n===========【备份元素】===============\n");
if((fp=fopen("student.txt", "w+"))==NULL); //以只写形式打开文件,若失败,则返回NULL,并新建一个文件
{
for (i=0;in;i++)
{
fprintf(fp, "%d\n",q->element);
q=q->link;
}
}
printf("保存成功!!!\n");
fclose(fp); //关闭文件
system("pause");
system("cls");
}
主函数:
//主函数
int main()
{
while(1)
{
menu();
}
return 0;
}