02142 <数据结构导论> 第二章 线性表

2.1 线性表的基本概念

  • 线性表(Linear List) 是一种线性结构, 它是由n(n>=0)个数据元素组成的有穷序列, 数据元素又称结点.结点个数n称为表长, 当n=0时, 线性表不含有任何数据元素, 称为空表, 记为()
  • 基本特征: 线性表中结点具有一对一的关系, 如果结点数不为零, 则除起始结点没有直接前驱外, 其它结点有且仅有一个直接前驱; 除终端结点没有直接后继外, 其它结点有且仅有一个直接后继.
  • 线性表基本运算及功能描述:
  1. 初始化Initate(L): 建立一个空表L=0, L不含数据元素
  2. 求表长Length(L): 返回线性表的长度.
  3. 读取表元素Get(L, i): 返回线性表第i个元素
  4. 定位 Locate(L, x): 查找线性表中数据元素值等于x的结点序号,若有多个, 则返回最小值, 若没有找到, 则返回0
  5. 插入 Insert(L, x, i): 在线性表L中的第i个元素之前插入一个值为x的新数据元素,
  6. 删除 Delete(L, i): 删除线性中第i个元素

2.2 线性表的顺序存储

线性表的顺序存储方法是: 将表中的结点依次存放在计算机内存中一组连续的存储单元中, 数据元素在线性表中的紧邻关系决定它们存储空间中的存储位置, 即逻辑结构中相邻的结点其存储位置也相邻.用顺序存储实现的线性表称为顺序表, 一般使用数据来表示顺序表.
一般情况下, 元素比较和移动的次数为: n-i+1次, 如:顺序表有9个元素, 在第3个元素前插入一个新的元素,则需要移动的元素个数为: 9-3+1 =7个

2.3 线性表的链接存储

分为: 单链表, 循环链表, 双向循环链表, 最简单的是单链表

2.3.1单链表

data部分称为数据域,用于存储线性表的一个数据元素,
next部分称为指针或链域, 用于存放一个指针, 该指针指向本结点所含数据元素的直接后继结点.
所有结点通过指针链接形成链表(Link List),head称为头指针变量,该变量的值是指向单链表的第一个结点的指针.

2.3.2 线性表的基本运算:

  1. 初始化
LinkList InitiateLinkList() {
	LinkList head; //头指针
	head = malloc(sizeof(Node));   //动态构建一结点, 它是头结点
	head->next=NULL;   //该结点的指针域的值为NULL
	return head;
}
  1. 求表长
int LengthLinkList(LinkList head){
	Node * p = head;  // 定义p为工作指针, 指向头结点
	int cnt =0;   //初始化计数器为0
	while(p->next != NULL) {  // 判断是否为尾结点
		p = p->next;   // 将指针移动到下一个结点
		cnt++;
	}
	return cnt;
}
  1. 读表元素
// 在单链表中, 查找第i个元素结点, 若找到, 则返回指向该指针结点的指针; 否则返回NULL
Node *GetLinklist(LinkList head, int i){
	Node *p;  // 定义一个工作指针
	p=head->next //初始化指向头结点
	int c = 1;
	while((c<=i) && (p!=NULL)){
		p=p->next;
		c++;
	}
	if i==c return p;
	else return NULL;

}
  1. 定位
// 求表中第一个值等于x的结点的序号, 若不存在这种节点,返回结果为0
int LocateLinkList(LinkList head, DataType x){
	Node *p;
	p=head->next;
	int c=0;
	while(p!=NULL && p->data!=x){
		i++;
		p=p->next;
	}
	if (p!=NULL) return i+1;
	else return 0;
}

  1. 插入
    算法文字描述:
    将给定值x插入链表head中的第i个结点之前:
    先找到第i-1个结点q, 然后生成一值为x的新结点p, p的指针指向q的直接后继结点, q的指针域指向p, 这样即可完成单链表的插入运算.
void InsertLinklist(LinkList head, DataType x, int i){
	Node *p, *q;
	if (i==1) q=head;
	else q = GetLinklist(head, i-1);
	if (q==NULL) exit("找不到指定位置")
	else {
	p = malloc(sizeof(Node)); //生成新的结点
	p->data = x;  //新结点的数据域为x
	p->next = q->next; // p结点next域指向q结点的指针域
	q->next =p; //q结点的指针域指向p
}
}
  1. 删除
    算法文字描述:
    给定一个值i, 将链表中第i个结点从链表中移出, 并修改相关结点的指针域, 以维持剩余结点的链接关系.
void DeleteLinklist(LinkList head, int i){
	Node *q, *p;
	if (i==1) q=head;
	else q = GetLinklist(head, i-1);  // 先找到直接前驱结点
	if (q!=NULL && q->next!=NULL){  // 若直接前驱结点存在且存待删结点存在
		p=q->next;  // 指向待删结点
		q->next = p->next;  //移出待删结点
		free(p);  // 释放已删除的节点空间
	else exit("找不到结点")
	
}

}

2.5 其他链表

2.5.1 循环链表

在单链表中, 如果让最后一个结点的指针域指向第一个结点可以构成循环链表. 在循环链表中,从任一结点出发都能够扫描整个链表.

2.4.2 双向循环链表

在单链表中, 每个结点中再设置一个指向其直接前驱的指针域(prior), 这样每个节点有两个指针
prior data next

你可能感兴趣的:(02142,数据结构导论,自考,线性表)