数据结构——链表

一、概念

  • 线性表:多个数据元素组成的有限序列。
  • 链表:线性表的链式存储结构

二、分类

1.单链表

  • 概念: 链表的结点包含数据域和指针域,指针域只有一个,并指向下一个结点。
  • 特点:插入删除数据的时间复杂度仅为O(1),不需要预分配存储空间。

2. 循环链表

  • 概念:单链表中,终端结点的指针由空指针改为指向头结点的指针,形成一个环。
  • 特点:相对于单链表,循环链表可以在任意位置开始访问到整个链表,尾指针的存在方便了链表的合并。

3. 双向链表

  • 概念:结点中除数据域以外包含两个指针域,一个指向前驱结点,一个指向后继结点。
  • 特点:相对于单项链表可以实现双向的查找。

三、单链表

    注:C语言实现,包括单链表的创建、增加数据、查询某一个数据、删除某个结点、获取链表长度等。

/**
 * singly_linked_list.c
 * 
 * Created on: 2020年1月27日
 *     Author: Beyonderwei
 */

/*----------单链表----------*/
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>


// 定义链表元素所存储的数据类型
typedef int ElemType;
// 定义节点的存储结构
typedef struct Node
{
  /* data */
  ElemType data;
  struct Node *next;
}Node;
// 定义链表指针
typedef struct Node *LinkList;

/**
 * Function 创建带有头节点的单链表,即创建一个头节点
 * @param:
 *    list: 链表
 * @return 指向链表的指针
 */
LinkList createList(void)
{
  LinkList list;
  list = (LinkList)malloc(sizeof(Node));
  list->next = NULL;
  return list;
}

/**
 * Function 向链表追加数据
 * @param:
 *    list: 链表
 *    elem: 要追加的数据
 * @return 指向链表的指针
 */
LinkList listAppend(LinkList list, ElemType elem)
{
  LinkList tmp, node;
  tmp = list;
  while(tmp->next)
  {
    tmp = tmp->next;
  }
  node = (LinkList)malloc(sizeof(Node)); //生成一个新的节点,来存储数据
  node->data = elem;
  node->next = NULL;
  tmp->next = node;
  return list;
}

/**
 * Function 按照条件查找链表中的某个元素
 * @param:
 *    list: 链表
 *    elem: 要查找的数据
 * @return 指向该结点的指针
 */
LinkList getElem(LinkList list, ElemType elem)
{
  LinkList tmp = list;
  while(tmp)
  {
    if(tmp->data == elem) // 可以改为按照data中的某个条件来查找
    {
      return tmp;
    }
    else
    {
      tmp = tmp->next;
    }
  }
  return NULL;
}

/**
 * Function 获取链表的长度
 * @param:
 *    list: 链表
 * @return 链表的长度(不包括头节点)
 */
unsigned int getLength(LinkList list)
{
  unsigned int length = 0;
  LinkList tmp;
  tmp = list;
  while(tmp->next)
  {
    length++;
    tmp = tmp->next;
  }
  return length;
}

/**
 * Function 按照条件删除链表的某一个结点
 * @param:
 *    list: 链表
 *    elem: 要删除的元素
 * @return list: 删除成功
 *         NULL: 删除失败
 */
LinkList deleteElem(LinkList list, ElemType elem)
{
  LinkList last_node;
  LinkList tmp = list;
  while(tmp->next)
  {
    last_node = tmp;
    tmp = tmp->next; //因为头结点没有存储数据,直接略过
    if(tmp->data == elem)
    {
      last_node->next = tmp->next;
      free(tmp);
      return list;
    }
  }
  return NULL;
}

/*---------测试代码----------*/
void main(void)
{
  LinkList list;
  unsigned int length;
  list = createList();
  LinkList e;
  listAppend(list, 1);
  listAppend(list, 2);
  listAppend(list, 3);
  listAppend(list, 4);
  listAppend(list, 5);
  listAppend(list, 6);
  
  deleteElem(list, 7);
  deleteElem(list, 5);
  length = getLength(list);
  printf("链表长度为:%d\n",length);
  e = getElem(list, 6);
  if(e != NULL)
  {
    printf("查询的值为:%d\n",e->data);
  }
  printf("链表第一个元素:%d",list->next->data);
}

四、循环链表与双向链表

    对于以上功能的实现仅仅是在单项链表上做了一些改变。

  
  
Email : Beyonderwei@Gmail.com
Website : http://beyonderwei.com
  
WeChat:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值