#include <stdio.h>
#include <string.h>
#include "stdlib.h"
#include "time.h"
#define OK 1
#define Error 0
#define True 1
#define False 0
typedef int Elemtype;
typedef int Status ;
/**
* @ filename :线性链式存储(单向链表的创建,数据的插入,数据的删除等操作)
* @ Date: 2019-2-27
* @ Version:V1.0
* @ 参考:https://blog.csdn.net/qq_33573235/article/details/79439268
*/
/*****************************************
*
* 函数功能:输出字符
*
*******************************************/
Status Visit(int c)
{
printf("%d\n",c);
return OK;
}
//定义节点
//单向链表节点主要是有两部分组成:数据域与地址域
typedef struct Node
{
Elemtype data;
struct Node *next;
}Node;
//定义链表linklist
typedef struct Node *Linklist;
/*
* 函数功能:初始化链表
* 初始化链表的关键点:在堆上开辟内存空间产生头节点,并上*L指向此头节点,初始化链表为空
*/
Status InitList(Linklist *L)
{
*L=(Linklist)malloc(sizeof(Node));
if(!(*L))//内存分配失败
{
return Error;
}
(*L)->next=NULL;
return OK;
}
/*
* 函数功能: clear the all over the linklist
* 函数说明当整个链表已经存在,操作的步骤是将整个表置为空表
* 删除思路:(使用二级指针)
* 定义两个节点,一个节点用来访问整个链表,一个用来临时存放的问题
*/
Status ClearList(Linklist *L)
{
Linklist p,q; //声明节点
p=(*L)->next;//p指向头节点
while(p) //链表不为空的情况下
{
q=p->next;//Q用来临时记录p的下一个节点
free(p);
p=q;
}
(*L)->next=NULL;//头结点的指针域为空
}
/*
* 函数功能: 返回链表中元素的个数
* 函数说明当整个链表已经存在,操作的步骤是将整个表置为空表
* 删除思路:(使用一级指针)【不要对头结点的地址指针进行修改】
*/
int ListLength(Linklist L)
{
int i=0;
Linklist p=L->next;//定义P为头节点
while(p)
{
i++;
p=p->next;
}
return i;
}
/*
* 函数功能: 顺序线性表已经存在,用e返回链表中第i个元素的值
* 函数说明当整个链表已经存在,操作的步骤是将整个表置为空表
* 删除思路:(使用一级指针)【不要对头结点的地址指针进行修改】
* 入口参数说明:要取出数的位置i,
*/
Status GetElem(Linklist L,int i,int *e)
{
int j=1;//j为计数器
Linklist p;//声明一个节点
p=L->next;//定义P指向头节点
while(p&&j<i) //只要取出指针依次增加,没有到要取出数值的位置,p->next 就会一直增加
{
j++;
p=p->next;
}
if(!p || j>i)
return 0;
*e=p->data;
return OK;
}
/**
* 函数功能:顺序链表已经存在 ,1<i<ListLength(L)
在L中的第i 个之前插入数据元素e,链表的长度自动加1
*
*/
int ListInsert(Linklist L,int i,int e)
{
int j=1;//线性表的下标是从1开始的,这里用作计数器的作用
Linklist p,s;//定音两个新的节点,s为待插入的节点
p=L->next;//p指向链表的第一个节点
while(p&& j<i)
{
p=p->next;
j++;
}
if(!p &&j>i)
return i;
s=(Linklist)malloc(sizeof(Node));
s->data=e;
s->next=p->next;
p->next=s;
return OK;
}
/*初始条件:顺序线性链表已存在*/
/*操作结果:依次打印L中的每个元素*/
Status ListTraverse(Linklist L)
{
Linklist p;
p=L->next;//定义节点p 指向链表的第一个节点
while(p)
{
Visit(p->data);
p=p->next;
}
}
/***********************************************
* 函数功能:利用头插法实现随机产生n个元素的值,
* 建立带表头节点的单链表L
*
*////////////////////////////////////////////
void CreateListHead(Linklist *L,int n)
{
int i; //线性表的下表计数器
Linklist p;
srand(time(0));
*L=(Linklist)malloc(sizeof(Node));
(*L)->next=NULL;//建立一个空的链表
for(i=0;i<n;i++)
{
p=(Linklist)malloc(sizeof(Node));
p->data=rand()%100+1;
p->next=(*L)->next;
(*L)->next=p;
}
}
/* 初始条件:顺序线性表L已存在 */
/* 操作结果:返回L中第1个与e满足关系的数据元素的位序。 */
/* 若这样的数据元素不存在,则返回值为0 */
int LocateElem(Linklist L,int e)
{
int i=0;
Linklist p=L->next;
while(p)
{
i++;
if(p->data==e) /* 找到这样的数据元素 */
return i;
p=p->next;
}
return 0;
}
/* 初始条件:顺序线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */
Status ListEmpty(Linklist L)
{
if(L->next)
return 0;
else
return 1;
}
/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
/* 操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1 */
Status ListDelete(Linklist *L,int i,int *e)
{
int j;
Linklist p,q;
p = *L;
j = 1;
while (p->next && j < i) /* 遍历寻找第i个元素 */
{
p = p->next;
++j;
}
if (!(p->next) || j > i)
return 0; /* 第i个元素不存在 */
q = p->next;
p->next = q->next; /* 将q的后继赋值给p的后继 */
*e = q->data; /* 将q结点中的数据给e */
free(q); /* 让系统回收此结点,释放内存 */
return OK;
}
/***********************************************
* 函数功能:利用尾部插法实现随机产生n个元素的值,
* 建立带表头节点的单链表L
*////////////////////////////////////////////
void CreateListTail(Linklist *L,int n)
{
int i;
Linklist p ,r;
srand(time(0));
*L=(Linklist)malloc(sizeof(Node));
//r用来存放指向表尾的指针
r=*L;
for(i=0;i<n;i++)
{
p=(Linklist)malloc(sizeof(Node));
p->data=rand()%100+1;
r->next=p;
r=p;
}
r->next=NULL;
}
int main ()
{
Linklist L;
int e;
Status i;
int j,k;
i=InitList(&L);
printf("初始化L后:ListLength(L)=%d\n",ListLength(L));
for(j=1;j<=5;j++)
i=ListInsert(&L,1,j);
printf("在L的表头依次插入1~5后:L.data=");
ListTraverse(L);
printf("ListLength(L)=%d \n",ListLength(L));
i=ListEmpty(L);
printf("L是否空:i=%d(1:是 0:否)\n",i);
i=ClearList(&L);
printf("清空L后:ListLength(L)=%d\n",ListLength(L));
i=ListEmpty(L);
printf("L是否空:i=%d(1:是 0:否)\n",i);
for(j=1;j<=10;j++)
ListInsert(&L,j,j);
printf("在L的表尾依次插入1~10后:L.data=");
ListTraverse(L);
printf("ListLength(L)=%d \n",ListLength(L));
ListInsert(&L,1,0);
printf("在L的表头插入0后:L.data=");
ListTraverse(L);
printf("ListLength(L)=%d \n",ListLength(L));
GetElem(L,5,&e);
printf("第5个元素的值为:%d\n",e);
for(j=3;j<=4;j++)
{
k=LocateElem(L,j);
if(k)
printf("第%d个元素的值为%d\n",k,j);
else
printf("没有值为%d的元素\n",j);
}
k=ListLength(L); /* k为表长 */
for(j=k+1;j>=k;j--)
{
i=ListDelete(&L,j,&e); /* 删除第j个数据 */
if(i==0)
printf("删除第%d个数据失败\n",j);
else
printf("删除第%d个的元素值为:%d\n",j,e);
}
printf("依次输出L的元素:");
ListTraverse(L);
j=5;
ListDelete(&L,j,&e); /* 删除第5个数据 */
printf("删除第%d个的元素值为:%d\n",j,e);
printf("依次输出L的元素:");
ListTraverse(L);
i=ClearList(&L);
printf("\n清空L后:ListLength(L)=%d\n",ListLength(L));
CreateListHead(&L,20);
printf("整体创建L的元素(头插法):");
ListTraverse(L);
i=ClearList(&L);
printf("\n删除L后:ListLength(L)=%d\n",ListLength(L));
CreateListTail(&L,20);
printf("整体创建L的元素(尾插法):");
ListTraverse(L);
return 0;
}
线性表的单向存储(单链表完全操作)
猜你喜欢
转载自blog.csdn.net/weixin_42145502/article/details/87995806
今日推荐
周排行