首页 > 代码库 > 数据结构单链表实现

数据结构单链表实现

  《数据结构》中单链表的实现c代码      
转自:http://blog.chinaunix.net/uid-22750250-id-1769905.html
include.h

/******************************************************************
      程序中要用的头文件
******************************************************************/

 #include<string.h>
 #include<ctype.h>
 #include<malloc.h> // malloc()等

 #include<limits.h> // INT_MAX等

 #include<stdio.h> // EOF(=^Z或F6),NULL

 #include<stdlib.h> // atoi()

 #include<io.h> // eof()

 #include<math.h> // floor(),ceil(),abs()

 #include<process.h> // exit()

 #include<iostream.h> // cout,cin




/******************************************************************
      自定义头文件
******************************************************************/

#include "status.h"

 

list.h

#include "status.h"

//--------------线性表单链表的结构体-------------------------

typedef int ElemType;

struct LNode
{
    ElemType data;
    struct    LNode *next;
}LNode;
typedef struct LNode *LinkList;
//--------------线性表单链表的结构体-------------------------



/***********************************************************
* 函数声明 *
************************************************************/

Status InitList(LinkList *L);//初始化函数

Status ListInsert(LinkList *L,int i,ElemType e);//在带头结点的单链表插入数据

Status ListDelete(LinkList *L,int i,ElemType *e);//在带头结点的单链表L中删除第i个元素,并由e返回其值

Status ListEmpty(LinkList L);//判空函数

Status ClearList(LinkList *L);//置空函数

int ListLength(LinkList L);//计算L中元素个数函数

Status GetElem(LinkList L,int i, ElemType *e);//获取L中第i个元素的函数

int LocateElem(LinkList L,ElemType e,Status (*compare)(ElemType , ElemType));//LocateElem 函数

Status PriorElem(LinkList L,ElemType cur_e,ElemType *pre_e);//获取前驱函数

Status NextElem(LinkList L,ElemType cur_e,ElemType *next_e);//获取后继元素

Status ListTraverse(LinkList L,void(*vi)(ElemType));//Traverse函数 对L中的每个元素进行Vi访问 L中的数据不变

Status DestroyList(LinkList *L);


status.h

/******************************************************************
      程序中要用到的 函数结果状态代码
******************************************************************/

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
// #define OVERFLOW -2 因为在math.h中已定义OVERFLOW的值为3,故去掉此行

typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等

typedef int Boolean;


list.c

/******************************************************************************
               在list.h中声明函数的实现
             线性表单链表的基本操作有12个
******************************************************************************/

#include "include.h"
#include "list.h"


//-----------------------初始化函数------------------------------------------

Status InitList(LinkList *L)
{//操作结果:构造一个空的单链表

    (*L)=(LinkList)malloc(sizeof(LNode));//生产头结点并使L指向此头结点

    if(!(*L)) //非配失败

        exit(OVERFLOW);
    (*L)->next=NULL;

    return OK;
}

//-----------------------插入函数--------------------------------------------

Status ListInsert(LinkList *L,int i,ElemType e)
{//在带头结点的单链表中第i个位置之前插入元素e

    LinkList p=*L,s;
    int j=0;
    while(p&&j<i-1)
    { //寻找第i-1个结点

        p=p->next;
        j++;
    }
    if(!p||j>i-1) //i小于1或大于表长返回

        return ERROR;
    s=(LinkList)malloc(sizeof(LNode));//生成新结点

    s->data=e; //插入L中

    s->next=p->next;
    p->next=s;
    return OK;
}

//-----------------------删除函数-------------------------------------------

Status ListDelete(LinkList *L,int i,ElemType *e)
{//在带头结点的单链表L中删除第i个元素,并由e返回其值

    LinkList p=*L,q;
    int j=0;
    while(p->next&&j<(i-1)) //寻找第i个结点,并用p指向其前驱

    {
        p=p->next;
        ++j;
    }
    if(!(p->next)||j>(i-1)) //位置不合理

        return ERROR;
    q=p->next;
    p->next=q->next; //删除并释放结点

    *e=q->data;
    free(q);
    return OK;
}

//-----------------------判空函数-------------------------------------------

Status ListEmpty(LinkList L)
{//初始条件:L已存在。操作结果:如果L为空则返回TRUE,否则返回FALSE

    if(L->next)
        return FALSE;
    else
        return TRUE;
}
//-----------------------置空函数-------------------------------------------

Status ClearList(LinkList *L)
{//初始条件:L存在。 操作结果:将L置空。

    LinkList p,q;
    p=(*L)->next; //指向第一个节点

    while(p) //释放结点

    {
        q=p->next;
        free(p);
        p=q;
    }
    (*L)->next=NULL;//头结点指向空

    return OK;
}
//-----------------------计算L中元素个数函数-----------------------------------

int ListLength(LinkList L)
{//初始条件:L存在。操作结果:返回L中元素的个数

    LinkList p;
    int i=0;
    p=L->next; //p指第一个结点

    while(p)
    {
        p=p->next;
        ++i;
    }
    return i;
}

//-----------------------获取L中第i个元素的函数-----------------------------------

Status GetElem(LinkList L,int i, ElemType *e)
{//L为带头结点的单链表。

//当第i个元素存在时其值赋给e,并返回OK,否则返回FALSE

    LinkList p;
    int j=0;
    p=L->next; //指向第一个结点

    j=1;
    while(p&&j<i) //顺指针向后查找,知道p为空或p指向第i个元素

    {
        p=p->next;
        ++j;
    }
    if(!p||j>i) //第i个元素不存在

        return ERROR;
    *e=p->data; // 去第i个元素

    return OK;
}

//-----------------------LocateElem函数-----------------------------

int LocateElem(LinkList L,ElemType e,Status (*compare)(ElemType , ElemType))
{//初始条件:线性表存在,compare()是数据元素判定函数(满足为1,否则为0)

//操作结果:返回L中第一个与e满足关系compare()的数据元素的位序

    int i=0;
    LinkList p=L->next; //指向第一个元素

    while(p)
    {
        ++i;
        if(compare(p->data,e)) //找到这样的元素

            return i;
        p=p->next;
    }
    return 0;
}

//-----------------------获取前驱函数-----------------------------

Status PriorElem(LinkList L,ElemType cur_e,ElemType *pre_e)
{//初始条件:L已存在

//操作结果:cur_e是L中的元素且不是第一个,用pre_e返回它的前驱,

//成功返回OK;否则操作失败,pre_e无定义,返回INFEASIBLE

    LinkList q,p=L->next; //p指向第一个元素

    while(p->next) //向后查找

    {
        q=p->next; //q为p的后继

        if(q->data==cur_e)
        {
            *pre_e=p->data;
            return OK;
        }
        p=q; //下一个

    }
    return INFEASIBLE;
}


//-----------------------获取后继函数-----------------------------

Status NextElem(LinkList L,ElemType cur_e,ElemType *next_e)
{//初始条件:L已存在

//操作结果:cur_e是L中的元素且不是最后,用next_e返回它的前驱,

//成功返回OK;否则操作失败,next_e无定义,返回INFEASIBLE

    LinkList p=L->next;//p指向第一个元素 

    while(p->next) //所指结点的后继

    {
        if(p->data==cur_e)
        {
            *next_e=p->next->data;
            return OK;
        }
        p=p->next;
        
    }
    return INFEASIBLE;
    
}

//-----------------------visit函数----------------------------------

Status ListTraverse(LinkList L,void(*vi)(ElemType))
{// 初始条件:线性表L已存在

 // 操作结果:依次对L的每个数据元素调用函数vi()。一旦vi()失败,则操作失败

     LinkList p=L->next;//指向第一个元素

     while(p)
     {
         vi(p->data);
         p=p->next;     
     }
     printf("\n");
     return OK;
}
//-----------------------销毁函数----------------------------------

Status DestroyList(LinkList *L)
{ // 初始条件:线性表L已存在。操作结果:销毁线性表L

   LinkList q;
   while(*L)
   {
     q=(*L)->next;
     free(*L);
     *L=q;
   }
   return OK;
}


main.c

 

#include "include.h"
#include "list.h"



Status compare(ElemType c1,ElemType c2)
{//比较两个数是否相等

    if(c1==c2)
        return TRUE;
    else
        return FALSE;
}

void visit(ElemType c) 
{
   printf("%d ",c);
}

void main()
{
    LinkList L,p;
    Status result;
    ElemType e;
    int i=0;
    //------------------------初始化函数测试-------------------------------

    result=InitList(&L);
    printf("初始化L后:L=%u\n",L);
    //---------------------------------------------------------------------

    //-----------------------判空函数测试----------------------------------

    result=ListEmpty(L);
    if(result)
        printf("L 为空\n");
    else
        printf("L 不为空\n");
    //---------------------------------------------------------------------

    
    //-------------------------插入函数测试--------------------------------

    for(i=1;i<=5;i++)
        ListInsert(&L,1,i);
    printf("插入元素后的 L :\n");
    p=L; //p指向头结点

    while(p->next)
    {    
        printf(" %d ",p->next->data);
        p=p->next;
    }
    printf("\n");
    //---------------------------------------------------------------------


    //-----------------------删除函数测试----------------------------------

    printf("删除第4个元素\n");
    ListDelete(&L,4,&e);
    printf("删除后的 L :\n");
    p=L; //p指向头结点

    while(p->next)
    {
        printf(" %d ",p->next->data);
        p=p->next;
    }
    printf("\n");
    //---------------------------------------------------------------------


    //-----------------------判空函数测试----------------------------------

    result=ListEmpty(L);
    if(result)
        printf("L 为空\n");
    else
        printf("L 不为空\n");
    //---------------------------------------------------------------------

    //-----------------------置空函数测试----------------------------------

    printf("将L置空\n");
    result=ClearList(&L);
    printf("置空后的L:\n");

    result=ListEmpty(L);
    if(result)
        printf("L 为空\n");
    else
        printf("L 不为空\n");

    //---------------------------------------------------------------------


    //-------------------------插入10个数--------------------------------

    for(i=1;i<=10;i++)
        ListInsert(&L,1,i);
    printf("插入元素后的 L :\n");
    p=L; //p指向头结点

    while(p->next)
    {    
        printf(" %d ",p->next->data);
        p=p->next;
    }
    printf("\n");
    //---------------------------------------------------------------------


    //-------------------------计算L中元素个数函数测试---------------------

    i=ListLength(L);
    printf("L中的元素的个数为:%d\n",i);
    //---------------------------------------------------------------------


    //-------------------------获取L中第i个元素的函数---------------------

    result=GetElem(L,6,&e);
    printf("第6个元素为:%d\n",e);

    //---------------------------------------------------------------------    


    //-------------------------LocateElem 函数函数测试---------------------

     printf("查看L中是否与4相等的元素\n");
     if(i=LocateElem(L,4,compare))
         printf("第%d个元素与4相等\n",i);
     else
         printf("没有与4相等的数据元素\n");
    

    //---------------------------------------------------------------------

    //-------------------------获取前驱函数测试----------------------------

     printf("获取元素4的前驱元素\n");
     //result=PriorElem(L,42,&e); //没有的数据 将获取失败

     result=PriorElem(L,4,&e);
     if(result==OK)
          printf("元素4的前驱元素为:%d\n",e);
     else
         printf("获取失败\n");
    
    
    //---------------------------------------------------------------------

    //-------------------------获取后继函数测试----------------------------

     printf("获取元素4的后继元素\n");
     result=PriorElem(L,42,&e); //没有的数据 将获取失败

     //result=NextElem(L,4,&e);

     if(result==OK)
          printf("元素4的后继元素为:%d\n",e);
     else
         printf("获取失败\n");
    
    
    //---------------------------------------------------------------------

    //-------------------------ListTraverse函数测试------------------------

    printf("ListTraverse函数测试,输出L中的所有元素。\n");
    result= ListTraverse(L,visit);
    printf("\n");
    //---------------------------------------------------------------------

    //-------------------------销毁函数测试--------------------------------

    printf("销毁L前:L=%u\n",L);
    printf("销毁L...\n");
    DestroyList(&L);
    printf("销毁L后:L=%u\n",L);
    //---------------------------------------------------------------------

    
}