数据结构之单链表

来源:互联网 发布:零基础学算法进制 编辑:程序博客网 时间:2024/05/22 10:34

链表:存储结构的一种,包含两个部分,数据域和指针域,相对于顺序存储结构来说,插入和删除的算法时间复杂度只为O(1).

定义:

//定义typedef struct Node *LinkList;   //linkList,指针指向每一个元素typedef struct Node{          //每个元素的构成     ElemType data;              //数据域     struct Node *next;          //指针域 }Node; 

注意:假设结点p表示一个结点A,那么p->next表示的下一个结点B,p->next也表示结点A的指针域,故,指针域存放的是指向下一个结点的指针。

以下为简单的C语言实现:

#include "stdio.h"    #include "string.h"#include "ctype.h"      #include "stdlib.h"   #include "io.h"  #include "math.h"  #include "time.h"#define OK 1#define ERROR 0#define TRUE 1#define FALSE 0#define MAXSIZE 20 /* 存储空间初始分配量 */typedef int Status;typedef int ElemType;//定义typedef struct Node *LinkList;   //linkList,指针指向每一个元素typedef struct Node{          //每个元素的构成     ElemType data;              //数据域     struct Node *next;          //指针域 }Node; //初始化Status InitList(LinkList *L){    *L = (LinkList)malloc(sizeof(Node));    //产生头结点,使得L指向分配到的头结点    if(!(*L)){        //如果分配失败         return ERROR;    }     (*L)->next = NULL;//指针域为空     return OK; } //获取第几个元素 Status GetElem(LinkList L,int i,ElemType *e){    int j;    LinkList p;     /* 声明一结点p */    p = L->next;        /* 让p指向链表L的第一个结点 */    j = 1;      /*  j为计数器 */    while (p && j<i)  /* p不为空或者计数器j还没有等于i时,循环继续 */    {           p = p->next;  /* 让p指向下一个结点 */        ++j;    }    if ( !p || j>i )         return ERROR;  /*  第i个元素不存在 */    *e = p->data;   /*  取第i个元素的数据 */    printf("第%d元素为%d\n",i,*e);    return OK;}//判断是否为空Status isEmptyList(LinkList L){    if(L->next){        return 1;    }else{        return 0;     }} //获取链表的长度int ListLength(LinkList L){    int i=0;    LinkList p ;    p = L->next;    while(p){        i++;        p = p->next;    }    return i;} //遍历链表 Status ListVisit(LinkList L){    LinkList p = L->next;    printf("该链表的元素为:\n");    while(p){        printf("%d ",p->data);        p = p->next;     }     printf("\n");     return OK; }//创建表,两种方法,头插法和尾插法 //头插法,在每一个头的开始不段插入,例如我们插入0-9,那么输出的结果就是9-0 void CreateListHead(LinkList *L,int n){    LinkList p;    int i;    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;                  //随机生成100以内的数字         p->next = (*L)->next;                           (*L)->next = p;                        //插入到头结点 ,即就是插入操作        } }//尾插法  ,最末尾元素后面插入,插入0-9 输出0-9 void CreateListTail(LinkList *L,int n){    LinkList p,r;    int  i;    srand(time(0));    *L = (LinkList)malloc(sizeof(Node));    r = *L;                 //r指向链表     for(i=0;i<n;i++){        p = (Node *)malloc(sizeof(Node));        p->data = rand()%100+1;        r->next = p;         /* 将表尾终端结点的指针指向新结点 */        r = p;              //将r赋值为新节点,下次指向的时候也就是把r指向了最末尾的结点,那么r也就是最末尾的结点     }    r->next = NULL;         //表示当前链表结束 } //重置表,也就是一个个结点的释放 Status ListClear(LinkList *L){    LinkList p,q;    p = (*L)->next;    while(p){        q = p->next;   //每一次指向然后释放         free(p);        p = q;         // 释放后    重新赋给其原来的q结点的位置     }    (*L)->next = NULL;     //头结点指针域赋值为空     printf("清空完成\n");    return OK;}//查找表中元素int LocateEle(LinkList L,ElemType e){    int i=0;    LinkList p;    p = L->next;          //指向链表,也就会指向头结点    while(p){        i++;        if(p->data == e){            printf("元素%d在第%d个位置\n",e,i);             return i;        }        p = p->next;    }     return 0;}//插入元素到表Status ListInsert(LinkList *L,int i,ElemType e){    int j;    LinkList p,s;               //创建两个结点p  s    p = *L;                     //指向一个链表    j=1;    //查找到第i个结点     while( p &&j<i){        p = p->next;        ++j;    }     if(!p || j>i){        return ERROR;    }    s = (LinkList)malloc(sizeof(Node));        //为新插入的分配一个结点     s->data = e;    s->next = p->next;                    //将原来p的后继结点赋给s的 后继     p->next = s;                         //将s赋给p的后继 ,注意以上两条语句的位置不能倒置    return OK;} //删除表中元素 Status ListDelete(LinkList *L,int i,ElemType *e){    int j;    LinkList p,q;    p = *L;    j=1;    while(p->next &&j<i){        p = p->next;        ++j;    }    if(!(p->next)  || j>i){        return ERROR;    }    q = p->next;             //先将p的后继赋给一个我们设置为q的结点,这个结点就是我们要删除的     p->next = q->next;       //将原来q的后继赋给p的后继     *e = q->data;            //将要删除的元素的值赋给*e     printf("删除的元素为%d:\n",*e);    free(q);                //记得free     return OK;}int main(){    LinkList L;    ElemType e;    Status i;    int j,k;    //初始化链表    i = InitList(&L);    printf("初始化完成后插入的链表为\n");    for(j=1;j<=5;j++){        ListInsert(&L,1,j);    }    ListVisit(L);    //插入单个元素    ListInsert(&L,2,100);    e = 100;    LocateEle(L,e);    ListVisit(L);    //删除元素    ListDelete(&L,2,&e);    ListVisit(L);    //获取第几个元素    GetElem(L,5,&e);    //清空重置    ListClear(&L);    ListVisit(L);    //头插法    CreateListHead(&L,10);        ListVisit(L);    //尾插法      CreateListTail(&L,10);        ListVisit(L);    return 0;}

这里写图片描述

0 0
原创粉丝点击