数据结构单链表实现

《数据结构》中单链表的实现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);
    //---------------------------------------------------------------------

    
}

时间: 2024-10-13 01:02:57

数据结构单链表实现的相关文章

python实现数据结构单链表

#python实现数据结构单链表 # -*- coding: utf-8 -*- class Node(object): """节点""" def __init__(self, elem): self.elem = elem self.next = None # 节点一开始初始化的时候并不知道下一个元素的地址,所以先设置为空 class SingLinkList(object): """单链表""

数据结构—单链表(类C语言描写叙述)

单链表 1.链接存储方法 链接方式存储的线性表简称为链表(Linked List). 链表的详细存储表示为: ① 用一组随意的存储单元来存放线性表的结点(这组存储单元既能够是连续的.也能够是不连续的) ② 链表中结点的逻辑次序和物理次序不一定同样.为了能正确表示结点间的逻辑关系,在存储每一个结点值的同一时候,还必须存储指示其后继结点的地址(或位置)信息(称为指针(pointer)或链(link)) 注意: 链式存储是最经常使用的存储方式之中的一个.它不仅可用来表示线性表.并且可用来表示各种非线性

C# 数据结构 - 单链表 双链表 环形链表

链表特点(单链表 双链表) 优点:插入和删除非常快.因为单链表只需要修改Next指向的节点,双链表只需要指向Next和Prev的节点就可以完成插入和删除操作. 缺点:当需要查找某一个节点的时候就需要一个节点一个节点去访问,这样所花的时候就比较多了.(顺序表可以弥补这缺点,但插入和删除就非常耗性能) 单链表 单链表的构成:必须要有一个链表头(head),每个节点里面有一个Next用于指向下一个节点(类似于指针).最后一个节点的Next为null来标识链表的尾. 如下图 代码实现 1 /* ----

C# 数据结构--单链表

什么是单链表 这两天看到很多有关单链表的面试题,对单链表都不知道是啥的我.经过学习和整理来分享一下啥是单链表和单链表的一些基本使用方法.最后看些网上有关单链表的面试题代码实例. 啥是单链表? 单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素.这组存储单元既可以是连续的,也可以是不连续的. 链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据. 链表的结点结构

数据结构-单链表-类定义2-C++

上一次的C++链表实现两个单链表的连接不太理想,此次听了一些视频课,自己补了个尾插法,很好的实现了两个链表的连接,当然了,我也是刚接触,可能是C++的一些语法还不太清楚,不过硬是花了一些时间尽量在数据结构中将c++的语言特点表现出来.一开始也是不愿意读c++的数据结构,只是一种挑战心里,不想读着读着感觉自己太low了,c++的内容更加丰富,所以还得多多练习...... 头文件 1 #ifndef LIST_H 2 #define LIST_H 3 #include <iostream> 4 5

Java数据结构——单链表

一.单链表的概念 单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素.这组存储单元可以是连续的,也可以是不连续的. 存储单元由两部分组成,数据源和指针,数据源放数据,指针指向下个存储单元. 二.单链表的结构 采用Node实体类类标识,其中data为存储的数据,next为下一个结点的指针. //链表的实体类 class Node{ public int data; public Node next; public Node(int data) { this.data =

大话数据结构---单链表

单链表在存储结构上与顺序存储的区别:不用开辟连续的存储空间,存储位置任意,只需要让数据的前驱知道它的位置就可以,而使用单链表示只需要知道单链表的第一个元素就能找到其他所有的元素,为了方便 一般会设置一个头指针指向第一个元素. 单链表的数据读取:通过头指针一个一个往后遍历 单链表的插入: 删除: 自定义单链表的简单实现: package com.neuedu.entity; /* * 项目名称:JavaSqList * @author:wzc * @date 创建时间:2017年9月2日 上午9:

C实现通用数据结构--单链表

单链表概述 单向链表(单链表)是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始. 从概念上讲,可以把链表想象成一系列连续的元素,然而,由于这些元素是动态分配的(C语言中使用malloc),切记这些元素通常实际上都是分散在内存空间的 本文地址:http://www.cnblogs.com/archimedes/p/c-datastruct-linklist.html,转载请注明源地址. 单链表的接口定义: 1.list_init void list_init(Li

数据结构——单链表

1.对于一个有数据的单链表,如果要对其初始化,使用下列操作: 1 void initList(sqlist &L){ #对于需要改变的变量或链表,使用引用型 2 L.length==0; 3 } //单链表长度重置为0 2.单链表有4中操作:归并,插入,删除,查找 归并的实现:(链表A,B是有序的,且归并后的C也是有序的)如下: 1 void merge(LNode *A,LNode *B,LNode *&C){ //将A B两个链表归并为一个新的单链表(链表C采用引用型) 2 LNode