码迷,mamicode.com
首页 > 其他好文 > 详细

数据结构:线性表

时间:2018-05-03 00:56:59      阅读:203      评论:0      收藏:0      [点我收藏+]

标签:如何   数组   数据结构   length   table   双向链表   group   .com   lap   

线性表设计与实现

线性表基本概念

线性表定义

线性表(List)是零个或多个数据元素的集合

线性表中的数据元素之间是有顺序的

线性表中的数据元素个数是有限的

线性表中的数据元素的类型必须相同

技术分享图片

数学定义

线性表是具有相同类型的 n( ≥ 0)个数据元素的有限序列(a1, a2, …, an)ai是表项,n 是表长度。

性质

a0为线性表的第一个元素,只有一个后继

an为线性表的最后一个元素,只有一个前驱

除a0和an外的其它元素ai,既有前驱,又有后继
线性表能够逐项访问和顺序存取

练习

下面的关系中可以用线性表描述的是

A.班级中同学的友谊关系

B.公司中的上下级关系

C.冬天图书馆排队占座关系

D.花名册上名字之间的关系

线性表的操作

创建线性表

销毁线性表

清空线性表

将元素插入线性表

将元素从线性表中删除

获取线性表中某个位置的元素

获取线性表的长度

 

线性表在程序中表现为一种特殊的数据类型

线性表的操作在程序中的表现为一组函数

C语言描述=====》线性表的设计与实现

#ifndef _WBM_LIST_H_

#define _WBM_LIST_H_

 

typedef void List;

typedef void ListNode;

 

//创建并且返回一个空的线性表

List* LinkList_Create();

 

//销毁一个线性表list

void List_Destroy(List* list);

 

//将一个线性表list中的所有元素清空, 线性表回到创建时的初始状态

void List_Clear(List* list);

 

//返回一个线性表list中的所有元素个数

int List_Length(List* list);

 

//向一个线性表list的pos位置处插入新元素node

int List_Insert(List* list, ListNode* node, int pos);

 

//获取一个线性表list的pos位置处的元素

ListNode* List_Get(List* list, int pos);

 

//删除一个线性表list的pos位置处的元素 返回值为被删除的元素,NULL表示删除失败

ListNode* List_Delete(List* list, int pos);

 

#endif

 

线性表的顺序存储结构

1、基本概念

技术分享图片

2、设计与实现

插入元素算法

判断线性表是否合法

判断插入位置是否合法

把最后一个元素到插入位置的元素后移一个位置

将新元素插入

线性表长度加1

获取元素操作

判断线性表是否合法

判断位置是否合法

直接通过数组下标的方式获取元素

删除元素算法

判断线性表是否合法

判断删除位置是否合法

将元素取出

将删除位置后的元素分别向前移动一个位置

线性表长度减1

 

3、优点和缺点

优点:

无需为线性表中的逻辑关系增加额外的空间

可以快速的获取表中合法位置的元素

缺点:

插入和删除操作需要移动大量元素

当线性表长度变化较大时难以确定存储空间的容量

线性表的链式存储

1、基本概念

链式存储定义

为了表示每个数据元素与其直接后继元素之间的逻辑关系,每个元素除了存储本身的信息外,还需要存储指示其直接后继的信息。

技术分享图片

技术分享图片

表头结点

链表中的第一个结点,包含指向第一个数据元素的指针以及链表自身的一些信息

数据结点

链表中代表数据元素的结点,包含指向下一个数据元素的指针和数据元素的信息

尾结点

链表中的最后一个数据结点,其下一元素指针为空,表示无后继。

 

2、设计与实现

在C语言中可以用结构体来定义链表中的指针域

链表中的表头结点也可以用结构体实现

技术分享图片

技术分享图片

带头结点、位置从0的单链表

返回链表中第3个位置处,元素的值

LinkListNode* LinkList_Get(LinkList* list, int pos)

{

    int i = 0;

    TLinkList *tList = (TLinkList *)list;

    LinkListNode *current = NULL;

    LinkListNode *ret = NULL;

 

    if (list==NULL ||pos<0 || pos>=tList->length)

    {

        return NULL;

    }

    current = (LinkListNode *)tList;

    for (i=0; i<pos; i++)

    {

        current = current->next;

    }

    ret = current->next;

    return ret ;

}

 

返回第三个位置的

移动pos次以后,当前指针指向哪里?

答案:指向位置2,所以需要返回 ret = current->next;

 

备注:

    循环遍历时,    遍历第1次,指向位置0

            遍历第2次,指向位置1

            遍历第3次,指向位置2

            遍历第n次,指向位置n-1;

所以如果想返回位置n的元素的值,需要怎么做

    ret = current->next;

此问题是:指向头结点的指针移动n次 和 第n个元素之间的关系?

删除元素

技术分享图片

 

3、优点和缺点

优点:

无需一次性定制链表的容量

插入和删除操作无需移动数据元素

缺点:

数据元素必须保存后继元素的位置信息

获取指定数据的元素操作需要顺序访问之前的元素

循环链表

1、基本概念

循环链表的定义:将单链表中最后一个数据元素的next指针指向第一个元素

技术分享图片

循环链表拥有单链表的所有操作

创建链表

销毁链表

获取链表长度

清空链表

获取第pos个元素操作

插入元素到位置pos

删除位置pos处的元素

新增功能:游标的定义

在循环链表中可以定义一个"当前"指针,这个指针通常称为游标,可以通过这个游标来遍历链表中的所有元素。

技术分享图片

循环链表新操作

获取当前游标指向的数据元素

将游标重置指向链表中的第一个数据元素

将游标移动指向到链表中的下一个数据元素

直接指定删除链表中的某个数据元素

CircleListNode* CircleList_DeleteNode(CircleList* list, CircleListNode* node);

CircleListNode* CircleList_Reset(CircleList* list);

CircleListNode* CircleList_Current(CircleList* list);

CircleListNode* CircleList_Next(CircleList* list);

 

 

2、设计与实现

插入元素的分析

  1. 普通位置插入元素
  2. 添加第一个元素(第一次插入元素)
  3. 最后一个位置插入元素
  4. 第一个位置插入元素

在第一个位置插入

技术分享图片

技术分享图片

删除节点

技术分享图片

 

3、优点和缺点

优点:功能强了。

循环链表只是在单链表的基础上做了一个加强

循环链表可以完全取代单链表的使用

循环链表的Next和Current操作可以高效的遍历链表中的所有元素

缺点:

代码复杂度提高了

约瑟夫问题-循环链表典型应用

n 个人围成一个圆圈,首先第 1 个人从 1 开始一个人一个人顺时针报数,报到第 m 个人,令其出列。然后再从下一 个人开始从 1 顺时针报数,报到第 m 个人,再令其出列,…,如此下去,求出列顺序。

技术分享图片

 

双向链表

1、基本概念

单链表的结点都只有一个指向下一个结点的指针

单链表的数据元素无法直接访问其前驱元素

逆序访问单链表中的元素是极其耗时的操作!

len = LinkList_Length(list);

for (i=len-1; len>=0; i++) //O(n)

{

LinkListNode *p = LinkList_Get(list, i); //O(n)

//访问数据元素p中的元素

//

}

双向链表的定义

在单链表的结点中增加一个指向其前驱的pre指针

技术分享图片

双向链表拥有单链表的所有操作

创建链表

销毁链表

获取链表长度

清空链表

获取第pos个元素操作

插入元素到位置pos

删除位置pos处的元素

 

2、设计与实现

插入操作

技术分享图片

删除操作

技术分享图片

双向链表的新操作

获取当前游标指向的数据元素

将游标重置指向链表中的第一个数据元素

将游标移动指向到链表中的下一个数据元素

将游标移动指向到链表中的上一个数据元素

直接指定删除链表中的某个数据元素

DLinkListNode* DLinkList_DeleteNode(DLinkList* list, DLinkListNode* node);

DLinkListNode* DLinkList_Reset(DLinkList* list);

DLinkListNode* DLinkList_Current(DLinkList* list);

DLinkListNode* DLinkList_Next(DLinkList* list);

DLinkListNode* DLinkList_Pre(DLinkList* list);

//大家一定要注意:教科书不会告诉你 项目上如何用;哪些点是项目的重点;

做一个企业级的财富库,完成你人生开发经验的积累,是我们的学习重点,要注意!

 

3、优点和缺点

优点:双向链表在单链表的基础上增加了指向前驱的指针

功能上双向链表可以完全取代单链表的使用

循环链表的Next,Pre和Current操作可以高效的遍历链表中的所有元素

缺点:代码复杂

数据结构:线性表

标签:如何   数组   数据结构   length   table   双向链表   group   .com   lap   

原文地址:https://www.cnblogs.com/love-DanDan/p/8983203.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!