c::顺序表和链表

26 篇文章 0 订阅

这节来说下顺序表和链表吐舌头

【前言】:

1、什么是线性结构:n个数据元素的有序集合

    1)集合中必存在唯一的“第一个元素”

    2)集合中必存在唯一的“最后一个元素”

    3)除第一个元素外,其他的元素都只有一个后继

    4)除最后一个元素外,其他的元素都只有一个前驱

2、线性表


 1、顺序表

   1.1定义:

       把线性表中的节点按照逻辑次序存储在一组连续的地址单元中,在计算机中以数组的形式保存的线性表。

   1.2性质:

        在顺序表中每个节点的存储地址都是该节点在存储位置的线性函数,只要知道基地址和每个节点的大小,就可以找出任意一个节点。是一种 随机存储结构 。  

   1.3类型定义: 

  #define MAXSIZE 100 //表空间的大小可根据实际需要而定,这里假设为100
  typedef int DataType; 
  typedef struct  SeqList
{
      DataType array[MAXSIZE];//存放表结点
      size_t _size;//有效元素的个数
 }SeqList; 

   1.4特点

     1)存储的数据类型都相同
     2)可以在任意位置进行插入和删除

 2、链表

   1.1定义:

      用一组任意的存储单元来存储线性表的节点。它的形式是数据+指针,数据就是存储的数据元素,指针就是指向下一个数据的地址,将每一个孤立的节点链接起来

   1.2性质

      1) 是一种链式存储方式
      2)链表中的节点的逻辑次序和物理次序可能不相同

   1.3类型定义

typedef struct Node
{
	DataType data; //存储的数据
	struct Node* pNext; //指向下一个节点
}Node;

 3、顺序表和链表的比较

     1) 空间的开辟,顺序表一般是连续的开辟一段空间,然后进行数据的增删改查,因此空间大小是固定的(静态顺序表),而链表是实时的进行节点的申请和删除,所以空间是动态的,不固定大小。(动态顺序表是为了弥补静态顺序表的缺陷,空间还可以进行扩容)

     2) 当我们不知道要存储多少数据的时候,使用顺序表会造成空间的浪费,而链表是需要一个数据才申请一个节点,比起顺序表来说能在一定程度上节省空间。但是当我们知道要存储多少数据的时候使用顺序表最好,不会造成空间的浪费,而使用单链表就会造成内存碎片。

     3)对CPU高速缓存的影响: 
    因为顺序表的空间一般是连续开辟的,而且一次会开辟存储多个元素的空间,所以在使用顺序表时,可以一次把多个数据写入高速缓存,再写入主存,顺序表的CPU高速缓存效率更高,且CPU流水线也不会总是被打断;而单链表是每需要存储一个数据才开辟一次空间,所以每个数据存储时都要单独的写入高速缓存区,再写入主存,这样就造成了,单链表CPU高速缓存效率低,且CPU流水线会经常被打断。

从这儿看,貌似顺序表要更好一些,真是如此吗?继续看下去。

     ②、时间上的比较(Time)

a. 访问随机元素的时间复杂度: 
因为顺序表的结构就像是数组一样,可以用下标来访问它的元素,所以它的元素是支持随机访问的;相比之下,单链表的数据是链式存储的,它的元素是不支持随机访问的,想要知道某个元素,只能从头结点开始遍历整个链表,知道找到了该元素为止。因此顺序表访问随机元素的时间复杂度是O(1),而单链表访问随机元素的平均时间复杂度是O(n)。

b. 随机位置插入、删除元素的时间复杂度: 
因为顺序表的元素是连续存储的,因此要在特定位置插入、删除元素需要把它之后的元素全部后移或前移一个元素的位置,时间开销很大;而单链表在插入或删除元素时,只需要改变它的前驱元素及插入或删除元素的指向即可。因此,顺序表在插入随机位置插入、删除元素的平均时间复杂度是O(n),单链表在插入随机位置插入、删除元素的时间复杂度是O(1)。

一般来说线性表(顺序表和单链表都属于线性表)的插入删除操作会被执行的频繁一些,因此,使用单链表的频率较大
【小结】:

综合上述所言,顺序表和单链表各有各的优缺点,使用哪一种会好一些要结合具体的问题而言,不能一概而论。 
比如: 
在查询操作使用的比较频繁时,使用顺序表会好一些;在插入、删除操作使用的比较频繁时,使用单链表会好一些。

我在网上看到一张还比较好的表,大家可以结合我上面的描述,进行查看。大笑

比较基本的功能 #include <stdio.h> #include <stdlib.h> #include <ctype.h> typedef struct node{ char d; struct node *next; } node; node *findalpha(node *sor) /*提取字母*/ { node *nea; if (sor==NULL) { return NULL; } else if (isalpha(sor->d)) { nea=malloc(sizeof(node)); nea->d=sor->d; nea->next=findalpha(sor->next); } else return findalpha(sor->next); return nea; } node *finddigit(node *sor) /*提取数字*/ { node *nea; if (sor==NULL) { return NULL; } else if (isdigit(sor->d)) { nea=malloc(sizeof(node)); nea->d=sor->d; nea->next=finddigit(sor->next); } else return finddigit(sor->next); return nea; } node *findother(node *sor) /*提取其它字符*/ { node *nea; if (sor==NULL) { return NULL; } else if (!isdigit(sor->d)&&!isalpha(sor->d)) { nea=malloc(sizeof(node)); nea->d=sor->d; nea->next=findother(sor->next); } else return findother(sor->next); return nea; } int main(int argc, char* argv[]) { node *a=NULL,*b,*st,*alpha,*digit,*other; char c; while ((c=getchar())!='\n') /*读取字符并建表*/ { if (a==NULL) { a=malloc(sizeof(node)); st=a; a->d=c; } else{ b=malloc(sizeof(node)); b->d=c; a->next=b; a=b; } } a->next =NULL; a=st; puts("\nAll:"); while (a!=NULL) /*输出所有字符*/ { printf("%c",a->d); a=a->next ; } alpha=findalpha(st); digit=finddigit(st); other=findother(st); puts("\n\nLetter:"); while (alpha!=NULL) { printf("%c",alpha->d); alpha=alpha->next ; } puts("\n\nDigit:"); while (digit!=NULL) { printf("%c",digit->d); digit=digit->next ; } puts("\n\nOther:") ; while (other!=NULL) { printf("%c",other->d); other=other->next ; } return 0; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值