线性表

顺序表

特点:用一段地址连续的存储空间来依次顺序存放线性表中的各元素。是一种随机存储结构

定义

typedef  struct{ 
	datatype data[MAXSIZE];    
	int len;
} SeqList; 
  • SeqList L:定义一个顺序表L
  • SeqList *L:定义一个指向SeqList 类型的指针

基本运算

1. 初始化 Init_SeqList
SeqList *Init_SeqList(){
	SeqList *L;
	L = malloc(sizeof(SeqList));
	L->len = -1;
	return;
}
2. 插入运算Insert_SeqList

实现步骤
(1)将an~ai == 顺序向后==移动一个位置,即an移动到an+1,……,ai移动到ai+1,为待插入的新元素让出位置i;
(2) 将 e 放到空出的第i个位置;
(3) 修改 len 指针,使之恒指向当前表中最后一个元素。

int  Insert_SeqList(SeqList *L,int i,datatype e){  
	int j;
	if (L->len ==MAXSIZE-1){  
		printf(“表满溢出”); 
		return -1; 
	}
	if (i<1 || i>L->len +2){  /*检查插入位置i是否有效*/
		printf("位置错");
		return 0; 
	} 
	for( j=L->len ; j>=i-1 ; j--)
		L->data[j+1]=L->data[j];  /* 结点往后移动一个位置 */
	L->data[i-1]=e;     /*新元素e插入*/
	L->len ++;         /*len仍指向最后元素*/
	return 1;     /*插入成功,返回*/
} 

时间复杂度:O(n)

  • 平均移动数据元素的次数(加权平均数):
    Ein = ∑ i = 1 n + 1 \sum_{i=1}^{n+1} i=1n+1 pi (n - i + 1)
  • 设为等概率情况,即pi = 1/(n+1),则:
    Ein = ∑ i = 1 n + 1 \sum_{i=1}^{n+1} i=1n+1 pi (n - i + 1) = 1 n + 1 \frac{1}{n+1} n+11 ∑ i = 1 n + 1 \sum_{i=1}^{n+1} i=1n+1(n - i + 1) = n 2 \frac{n}{2} 2n
  • 平均需要挪动一半的元素。
3. 删除运算Delete_SeqList
4. 按值查找Locate_SeqList


单链表

特点:通过一组任意的存储单元来存储线性表中的数据元素,“链”保存的是其直接后继所在存储单元的起始地址。是一种顺序存储结构

定义

typedef struct node{
	datatype data;
	struct node *next;
} LNode, *LinkList;
  • LNode:结点类型
  • LinkList:指向LNode类型结点的指针类型

基本运算

1. 建立
(1)逆序建立单链表(头插法)
  • 设一个指针 L 始终指向单链表中的当前首结点(每插入一个结点,指针L向前移动一位,使其一直在首部)。
LinkList Creath_LinkList (){   
	LinkList L = NULL; /*空表,不指向任何地址*/
    LNode *s;
    int e;       /*设数据元素的类型为int*/
    scanf(%d", &e);
    while (e!=flag){     /*flag为设置的线性表数据元素结束标志*/
    	s = malloc(sizeof(LNode));  /*malloc()返回被分配内存的指针*/
        s->data = e; 
        s->next = L;  
        L = s;
        scanf (%d",&e);
	}
    return L;
}
(2)顺序建立单链表(尾插法)
  • 设一个指针 r 始终指向单链表中的当前尾结点
LinkList  Creatr_LinkList (){ 
	LinkList L = NULL;
    LNode *s, *r = NULL;
    int e;     /*设数据元素的类型为int*/
    scanf(%d",&e);
    while (e!=flag){ /*flag为设置的线性表数据元素结束标志*/
    	s = malloc(sizeof(LNode));     
       	s->data = e;
       	if(L==NULL)  L = s;  /*插入的结点是第一个结点*/
       	else  r->next = s;       /*插入的结点是其它结点*/
       	r=s;        /*r 恒指向新的尾结点*/
        scanf(%d",&e);
    }
    if( r!=NULL)  r->next = NULL; /*对于非空表,表尾结点的指针域置为空指针*/
    return L;
}
2. 求表长
  • 方法:设一个指针变量计数器,初始化后,如果该指针变量所指结点后面还有结点,该指针变量向后移动,计数器同时加1,直至该指针变量指向表尾。
///带头结点的单链表
int  Length_LinkList1 (LinkList  L)
{ LNode  * p=L;   /* p指向头结点*/
   int  i=0;      /* i是计数器*/
   while (p->next) 
    {p=p->next; i++ }   /* p所指的正是第 i 个结点*/
   return  i;
}

///不带头结点的单链表
int  Length_LinkList2 (LinkList L)
{  LNode  * p=L;
   int  i;    /* i是计数器*/
   if (p==NULL) return  0;  /*空表的情况*/
   i=1;  /*在非空表的情况下,p所指的是第一个结点*/
   while (p->next ) 
    { p=p->next;  i++ }
   return  i;
}
3. 查找
4. 插入
(1)在某结点之后插入 O(1)

在这里插入图片描述

s->next = p->next;
p->next = s;
(2)在某节点之前插入 O(n)

在这里插入图片描述

//设单链表头指针为L
q = L;
while(q->next!=p) q = q->next;  /*找*p的直接前驱*/
s->next = q->next;
q->next = s;

总结

  • 若想在单链表上插入、删除一个结点,必须知道其前驱结点
  • 不能按序号随机访问,只能从头结点开始顺着指针域顺序访问,该存取结构称为顺序存取结构
  • 如何选择存储结构? 顺序表(频繁查找);链表(频繁插入和删除)。

循环链表

只需要将原来寻找表尾时判断指针是否为NULL改为判断指针是否指向头结点即可。
在这里插入图片描述

双向链表

单链表中寻找后继结点的时间复杂度是O(1),寻找前驱结点的时间复杂度是O(n)。
若为每个结点再增加一个指向前驱的指针域prior,寻找前驱结点的时间性能也能达到O(1) 。

定义

typedef struct  dunode{ 
	datatype data;
  	struct dunode *prior,*next;	
}DulNode, *DulLinkList;
//特征:q->prior->next = q = q->next->prior

在这里插入图片描述

插入

///关键:要保证链表不能断
///已知的地址:s、q、q->prior
s->prior=q->prior;
q->prior->next=s;
s->next=q;
q->prior=s;

在这里插入图片描述

删除

q->prior->next=q->next;
q->next->prior=q->prior;
free(q); 

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值