9.24 数据结构-顺序表、单链表、双向链表、循环链表总结

一、数据结构绪论

概念:数据的组织方式,施加在数据上的一组操作,(增删改查等)。

1.1数据:能被计算机识别存储处理的符号集合。

数据分为数值类型和非数值类型

数值:int a,123,float b;等我们熟知的变量和常量都是数值数据。

非数值:mp3,光盘,磁带,电影视频。

1.2数据对象:多个数据对象构成了数据

例如:1班,2班,3班 都属于数据对象,构成班级属于数据。

1.3数据元素:多个数据元素构成了数据对象

例如:1班有27个(学生)数据元素。

1.4数据项:数据元素的最小组成单位。

例如:数据元素人有两条腿,有耳朵,有嘴,这些都是组成数据元素的最小单位。

数据>数据对象>数据元素>数据项

数据元素是组成数据的基本单位,数据项是数据的最小单位。

1.5数据结构体分为逻辑结构和物理结构体

顺序存储:逻辑相邻的元素物理上也相邻。

链式存储:逻辑相邻的元素物理上不一定相邻。

散列存储:哈希存储,数据元素的存储和哈希函数和关键字有关(了解)。

索引存储:在存储数据元素时建立一个索引表,以便快速查找。

1.6顺序存储和链式存储的区别

1、顺序存储必须占用连续的内存空间。

2、链式存储内存空间连续与否均可。

3、链式存储时节点体积较小,可以充分利用内存碎片。

4、相同节点个数的顺序存储和链式存储,链式存储占用内存较多。

5、链式存储和顺序存储都有优缺点,不能单纯的认为链式或者顺序存储较好。

 

二、线性表

例如:顺序表,顺序栈,顺序队列,顺序串,单链表,双链表,循环链表都属于线性表。

1、第一个元素没有前驱最后一个元素没有后继。

2、中间 的元素都有唯一的前驱和唯一的后继,元素之间一对一关系。

 三、顺序表(sequence)

3.1 概念

1、数据元素之间采用顺序存储的方式。

2、数据元素之间占用连续的内存空间。

3、采用数组存储顺序表。

3.2 实现方式

1、借助数组来存储顺序表。

2、数组长度固定

3、顺序表长度可变。

4、顺序表长度<=数组长度

 

 3.3顺序表的组成

1、顺序表借助数组来存储,封装结构体时需要封装数组。

2、顺序表长度不固定,所以还需要封装计数器,统计顺序表元素个数。

#define MAX 15//数组长度是15
typedef struct
{
    int data[MAX];//存储顺序表的数组
    int len;//统计顺序表长度的变量
}list,*Plist;
MAX:预估顺序表的存储长度最大值
data:存储顺便表的数组。
len:统计顺序表元素个数。
list:结构体普通类型。
Plist:结构体指针类型。

3.4有关顺序表的操作(功能函数)

创建顺序表

目标:存储班级所有学生信息,然后对班级同学进程增删改查,去重,排序,查找等。详见

9.19数据结构-顺序表-CSDN博客

3.5顺序表的优缺点

1、定位插入删除,移动大量元素,时间复杂度O(n).

2、定位查找修改,不需要移动元素,时间复杂度O(1)

3、冒泡排序时间复杂度O(n*n),改进的也是O(n*n).。

4、插入删除不方便,因为需要移动大量元素,并不是时间复杂度是O(n)

5、修改查找方便,因为不需要移动元素。

 3.6时间复杂度概念

时间复杂度分析是以最坏的情况分析。

T(n) = O(f(n));

T:时间复杂度的表示方法

n:问题的规模

O:渐进符号

f(n):代码总执行次数

int fun(int n,int a[])
{
    int i,j,t;//1次
    for(i = 1;i<n;i++)//n-1次
    {
        for(j = 0;j<n;j++)//n*(n-1)次
        {
               if(a[j]>a[j+1])//n*(n-1)次
               {
                   t = a[j];//n*(n-1)次
                   a[j] = a[j+1];//n*(n-1)次
                   a[j+1]=t;//n*(n-1)次               
               }     
        }    
    }
    return 0;//1次
}
T(n) = O(f(n))=O(5*n*(n-1)+(n-1)+1+1)=O(5*n*n-4*n+1)
O(5*n*n-4*n+1)---保留最高阶---> O(5*n*n)---系数化为1--->O(n*n)

 四、链表

4.1目的

1、插入删除不需要移动任何节点(元素)。

2、不需要预估存储空间大小,长度动态增长或减小。

4.2 概念

1、采用链式存储的线性表。

4.3 链表的种类

 五、单向链表

5.1 单向链表的概念

1、每个节点都有2部分组成,一部分是存储数据,一部分是存储地址。

2、节点描述:存储数据的叫数据域,存储地址的叫指针域。

3、单链表节点存在第0号节点(头节点),不存储数据,只存储节点个数len。

5.2单向链表节点结构体格式 

typedef struct zhangzhen
{
    union{
    int data;//用于正常节点,存储数据
    int len;//用于头节点,计算节点个数。
    };
    struct zhangzhen *next;//指针域,存储下一个节点地址
}link,*Plink;

5.3 单链表的相关操作

1>创建头节点
2>头插法创建单链表

3>尾插法创建单链表

4>遍历单链表

 5> 任意位置插入

6>任意位置删除 

7>任意位置查找

8>任意位置修改

 9>头删

10>尾删 

11>按值删除

 

12>按值修改
13>按值查找返回地址 
14>链表逆置

 

 

15>去重 

注意事项:删除重复的节点后,不需要移动 j ,继续将i与 j->next比较。 

16> 销毁

5.4单向链表的优缺点

优点:

1、插入删除不需要移动元素,只需要修改指针。

2、节点之间不连续,可以充分利用内存碎片存储数据。

3、不需要预估存储空间。

4、节点个数不受限制。

不足:

1、修改查找需要循环遍历节点。

2、相同长度的线性表,与顺序表相比单链表占用空间较多。

3、只能从头往后访问,不能反向访问。

总结:

1、单链表插入删除(头插,头删)时间复杂度O(1),查找修改,访问时间复杂度O(n)。

5.5 单链表实现学生管理系统

链接详见9.20 数据结构-单链表-CSDN博客

六、双向链表

6.1作用

1》单向链表只能单向访问链表,而双向链表可以正序或倒序访问查找链表

2》单向链表不能自我删除,每次都需要找到要删除结点的前一个结点进行删除,引入双向链表可以实现自我删除,找到要删除的结点,让要删除的前驱结点链接到要删除结点的后继结点,然后删除结点即可。

6.2 双向链表的相关操作(功能函数)

1>双向链表的创建

功能:创建一个双向链表头结点。

参数:void

返回值:申请到的头结点的地址指针

思路:在堆区申请一个头结点的空间大小,对其进行初始化,数据域len为0,指针域为NULL

注意:判断申请到的空间是否合法

2>头插

功能:在头结点的后面插入一个结点

返回值:成功1 失败0

参数:双向链表、要插入的元素

思路:1、给要插入元素申请结点

           2、将要插入的结点插在头结点的后面

           3、链表长度+1

注意:判断接收到的双向链表是否合法

1、没有1号节点时

     第一步、新节点p后指针置空

     第二步、新节点前指针指向头节点

     第三步、头节点后指针指向新节点

2、有1号节点时

      第一步、新节点后指针指向1号节点

      第二步、新节点前指针指向头节点

      第三步、1号节点前指针指向新节点

      第四步、头节点后指针指向新节点。

3>尾插 

1、没有1号节点时

     第一步、新节点p后指针置空

     第二步、新节点前指针指向头节点

     第三步、头节点后指针指向新节点

2、有1号节点时

      第一步、新节点后指针指向空

      第二步、新节点前指针指向 t

      第三步、t的后指针指向新节点p

 

4>双向链表的遍历 

功能:共头到尾输出双链表【也可以从尾到头输出双链表】

返回值:无

参数:双链表

思路:只要双链表不空,从头结点开始一个接着一个的输出

5>任意位置插入

功能:在双链表长度范围之内的任意位置,插入一个结点

返回值:成功1 失败0 int

参数:双链表、要插入的数据、指定的位置

思路:知道要插入的位置

 6>任意位置删除

7>链表任意位置查找、修改,按值查找、修改,排序,销毁等操作与单链表操作相同(同单链表)

七、循环链表

7.1概念

1、首尾相连的单链表或双链表。

7.2链表的相关操作(功能函数) 

链表的格式同不循环链表

对于功能函数来说,与不循环链表区别有以下,其余功能函数没有区别

创建链表时p->next=p;

Plink create()
{
    Plink p = malloc(sizeof(Link));
    if(NULL==p)
    {
        printf("申请失败\n");
        return NULL;
    }
    p->len = 0;
    p->next = p;//指向自己循环单链表
    return p;
}

尾插

尾删

 

 

Plink t  =L;
    for(i = 0;i<L->len-1;i++)
    {
        t = t->next;
    }
    Plink Q = t->next;//保留要删除的节点
    t->next= L;
    free(Q);
    Q  =NULL;
    L->len--;

销毁

PLink t=L->next,Q=t;
	while(t!=L){
		t=t->next;
		free(Q);	
		Q=t;
	}
	free(L);//最后再释放头节点
	printf("释放成功\n");

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值