单链表

来源:互联网 发布:python控制树莓派gpio 编辑:程序博客网 时间:2024/06/07 05:45

单链表:是一种链式存取的数据结构,用一组地址任意的存储单元这组存储单元既可以是连续的,也可以是不连续的存放线性表中的数据元素

单链表结构示意图:

单链表结构体定义

typedef struct Node{    ElemType data;    struct Node *next;}Node;typedef struct Node *LinkList; /* 定义LinkList */

单链表创建

创建单链表的过程就是一个动态生成链表的过程。即从“空表”的初始状态起,依次建立各元素结点并逐个插入链表。

思路

  1. 声明一个结点p和计数器变量i;
  2. 初始化一空链表L;
  3. 让L的头结点的指针指向NULL,即建立一个带头结点的单链表;
  4. 循环:  
    • 生成一新结点赋值给p;
    • 随机生成一数字赋值给p的数据域p->data;
    • 将p插入到头结点与前一新节点之间。
 实现代码 
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;/*  插入到表头 */}}
上述为头插法:即始终让新节点在第一的位置。图示如下:

另一种方法尾插法,即每次新节点都插在终端节点后面。
实现代码
/*  随机产生n个元素的值,建立带表头结点的单链线性表L(尾插法) */void CreateListTail(LinkList *L, int n) {LinkList p,r;int i;srand(time(0));                      /* 初始化随机数种子 */*L = (LinkList)malloc(sizeof(Node)); /* L为整个线性表 */r=*L;                                /* r为指向尾部的结点 */for (i=0; i<n; i++) {p = (Node *)malloc(sizeof(Node)); /*  生成新结点 */p->data = rand()%100+1;           /*  随机生成100以内的数字 */r->next=p;                        /* 将表尾终端结点的指针指向新结点 */r = p;                            /* 将当前的新结点定义为表尾终端结点 */}r->next = NULL;                       /* 表示当前链表结束 */}
单链表第i个数据读取
思路
  1. 声明一个结点p指向链表第一个结点,初始化j从1开始;
  2. 当j<i时,遍历链表,让p的指针向后移动,不断指向下一个结点,j累加1;
  3. 若到链表末尾p为空,则说明第i个元素不存在;
  4. 否则查找成功,返回结点p的数据。
实现
/* 操作结果:用e返回L中第i个数据元素的值 */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个元素的数据 */return OK;}
单链表插入与删除
单链表第i个数据插入结点的思路:
  1. 声明一结点p指向链表第一个结点,初始化j从1开始;
  2. 当j<i时,遍历链表,让p的指针向后移动,不断指向下一个结点,j累加1;
  3. 若到链表末尾p为空,则说明第i个元素不存在;
  4. 否则查找成功,生成一空结点s;
  5. 将数据元素e赋值给s->data;
  6. 单链表的插入标准语句s->next=p->next;p->next=s;
  7. 返回成功。
实现:
/* 操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1 */Status ListInsert(LinkList *L,int i,ElemType e){ int j;LinkList p,s;p = *L;   j = 1;while (p && j < i)     /* 寻找第i个结点 */{p = p->next;++j;} if (!p || j > i) return ERROR;   /* 第i个元素不存在 */s = (LinkList)malloc(sizeof(Node));  /*  生成新结点(C语言标准函数) */s->data = e;  s->next = p->next;      /* 将p的后继结点赋值给s的后继  */p->next = s;          /* 将s赋值给p的后继 */return OK;}

单链表第i个数据删除结点的思路
  1. 声明一结点p指向链表第一个结点,初始化j从1开始;
  2. 当j<i时,遍历链表,让p的指针向后移动,不断指向下一个结点,j累加1;
  3. 若到链表末尾p为空,则说明第i个元素不存在;
  4. 否则查找成功,将欲删除的结点p->next赋值给q;
  5. 单链表的删除语句p->next=q->next;
  6. 将q结点中的数据赋值给e,作为返回;
  7. 释放q结点;
  8. 返回成功;
实现
/* 操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1 */Status ListDelete(LinkList *L,int i,ElemType *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 ERROR;           /* 第i个元素不存在 */q = p->next;p->next = q->next;/* 将q的后继赋值给p的后继 */*e = q->data;               /* 将q结点中的数据给e */free(q);                    /* 让系统回收此结点,释放内存 */return OK;}



参考:
  1. 大话数据结构
  2. 《算法导论》



0 0
原创粉丝点击