线性表的单向存储(单链表完全操作)

#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
今日推荐