2022天勤考研数据结构笔记 第2章 线性表

第2章 线性表

线性表是具有相同特性数据元素的一个有限序列,其可以是一个空表。可以是有序的,也可以是无序的。

2.1 结构体定义

// 定义一个整形常量
# define maxSize 100

// 顺序表结构体定义
// 第一种表示
typedef struct{
	int data[maxSize];
	int length;
}Sqlist;
// 更为常见的表示
int A[maxSize];
int n;

// 单链表结点定义
typedef struct LNode{
	int data;
	struct LNode* next;
}LNode;

// 双链表结点定义
typedef struct DLNode{
	int data;
	struct LNode* prior;
	struct LNode* next;
}DLNode;

2.2 顺序表

  1. 基本操作
// 初始化
void initElem(Sqlist& L){
	L.length = 0;
}

// 求指定位置 p 的元素
int initElem(Sqlist L, int p, int& e){
	if(p < 0 || p > L.length - 1)
		return 0;
	e = L.data[p];
	return 1;
}

// 查找第一个值等于 e 的元素
int findElem(Sqlist L, int e){
	for(int i = 0; i < L.length; i++){
		if(e == L.data[i]) return i;
	}
	return -1;
}

// p 位置插入元素 e
int insertElem(Sqlist& L, int p, int e){
	if(p < 0 || p > L.length || L.length == maxSize)
	for(int i = L.length-1; i >= p; i--){
		L.data[i+1] = L.data[i];
	}
	L.data[p] = e;
	L.length++;
	return 1;
}

// 删除下标为 p 的元素
int deleteElem(Sqlist& L, int p, int& e){
	if(p < 0 || p > L.length - 1) return 0;
	e = L.data[p];
	for(int i = p; i < L.length - 1; i++){
		L.data[i] = L.data[i+1];
	}
	L.length--;
	return 1;
}
  1. 例子
// 已知一个递增有序排列的顺序表,设计一个算法,使插入元素 x 后该顺序表仍然递增有序排列
// 返回第一个比 x 元素大的元素位置
int findElem(Sqlist& L, int x){
	for(int i = 0; i < L.length; i++){
		if(L.data[i] > x){
			return i;	
		}
	}
	return i;	// 若不存在此元素, 则 i 正好标记表尾位置
}
// 插入 x 元素
void insertElem(Sqlist& L, int x){
	int p;
	p = findElem(L, x);
	for(int i = L.length - 1; i >= p; i--){
		L.data[i+1] = L.data[i];
	}
	L.data[p] = x;
	L.length++;
}

2.3 单链表

  1. 基本操作
// 数组 a 中存储 n 个元素,建立链表 C
// 头插法
void createListF(LNode*& C, int a[], int n){
	LNode* s;
	C = (LNode *)malloc(sizeof(LNode));
	C -> next = NULL;
	for(int i = 0; i < n; i++){
		s = (LNode *)malloc(sizeof(LNode));
		s -> data = a[i];
		s -> next = C -> next;
		C -> next = s;
	}
}
// 尾插法
void createListR(LNode*& C, int a[], int n){
	LNode* s, * r;
	C = (LNode *)malloc(sizeof(LNode));
	C -> next = NULL;
	r = C;
	for(int i = 0; i < n; i++){
		s = (LNode *)malloc(sizeof(LNode));
		s -> data = a[i];
		r -> next = s; 
		r = s;
	}
	r -> next = NULL;
}

//删除 p 位置的结点
int deleteList(LNode*& C, int p, int& e){
	if(p < 1 || p > L.length) return 0;
	LNode* s = C;
	
	for(int i = 0; i < p - 1; i++){
		s = s -> next;		//找到第 p-1个结点
	}
	if(s == NULL || s -> next == NULL) return 0;
	LNode* r = s -> next;
	e = r -> data;
	s -> next = r -> next;
	free(r);
	return 1;
}

//删除值为 x 的结点
int findAndDelete(LNode*& C, int x){
	LNode* p, * q;
	p = C;
	while(p -> next != NULL){
		if(p -> next -> data == x){
			break;
		}
		p = p -> next;
	}
	if(p -> next == NULL) return 0;
	q = p -> next;
	p -> next = q -> next;
	free(q);
	return 1;
}
  1. 例子
// A 和 B 是两个带头结点的单链表,元素递增有序
// 将 A 和 B 归并成一个按元素值 非递减 有序的链表 C
// 尾插法
void merge(LNode* A, LNode* B, LNode*& C){
	LNode *p = A -> next;
	LNode *q = B -> next;
	C = A;
	C -> next = NULL;
	free(B);
	LNode *s = C;
	while(p && q){
		if(p -> data <= q -> data){
			s -> next = p -> next;
			p = p -> next;
		}
		else{
			s -> next = q -> next;	
			q = q -> next;
		}
		s = s -> next; 
	}
	if(p){
		s -> next = p;
	}
	if(q){
		s -> next = q;
	}
}

// 设计一个算法,将 A 和 B 归并成一个按元素值 递减 有序的链表 C
// 头插法
void merge(LNode* A, LNode* B, LNode*& C){
	LNode *p = A -> next;
	LNode *q = B -> next;
	LNode *s;
	C = A;
	C -> next = NULL;
	free(B);
	while(p && q){
		if(p -> data <= q -> data){
			s = p;
			p = p -> next;
			s -> next = C -> next;
			C -> next = s;
		}
		else{
			s = q;
			q = q -> next;
			s -> next = C -> next;
			C -> next = s;
		}
	}
	while(p){
		s = p;
		p = p -> next;
		s -> next = C -> next;
		C -> next = s;
	}
	if(q){
		s = q;
		q = q -> next;
		s -> next = C -> next;
		C -> next = s;
	}
}

2.4 双链表

基本操作

// 尾插法建立双链表
void createDListR(DLNode*& L, int a[], int n){
	DLNode* s, * r;
	L =(DLNode *)malloc(sizeof(DLNode));
	L -> next = NULL;
	L -> prior = NULL;
	r = L;
	for(int i = 0; i < n; i++){
		s =(DLNode *)malloc(sizeof(DLNode));
		s -> data = a[i];
		r -> next = s;
		s -> prior = r;
		r = r -> next;
	}
	r -> next = NULL;
}

//查找第一个值为 x 的结点
DLNode* findNode(DLNode* C; int x){
	DLNode* p = C;
	while(p){
		if(p -> data == x) break;
		p = p -> next;
	}
	return p;		//包含未找到时 p = NULL 的情况
}

//在 p 后插入 s 
int insertDLNode(DLNode* p, DLNode* s){
	if(!p || !s) return 0;
	s -> next = p -> next;
	s -> prior = p;
	p -> next = s;
	if(p -> next){
		s -> next -> prior = s;
	}
	return 0;
}

//删除 p 的后继结点
int deleteDLNode(DLNode* p){
	if(!p || p -> next == NULL) return 0;
	DLNode* q = p -> next;
	p -> next = q -> next;
	if(q -> next){
		q -> next -> prior = p;
	}
	free(q);
	return 1;
}

2.5 循环链表

// p 为表尾结点的条件
  p -> next == head;

2.6 逆置问题(408重要考点)

// 逆置线性表中的元素
for(int i = left,j = right; i < j; i++, j--){
	int temp = 0;
	temp = a[i];
	a[i] = a[j];
	a[j] = temp;
}

// 将长度为 n 的数组前端 k(k < n) 个元素逆序后移动到数组后端,其余元素位置无关紧要
void reverse(int a[], int left, int right, int k){
	int temp = 0;
	for(int i = left, j = right; i < j; i++, j--){
		temp = a[i];
		a[i] = a[j];
		a[j] = temp;
	}
}

// 将长度为 n 的数组前端 k(k < n) 个元素保持原序移动到数组后端,其余元素位置无关紧要
void moveToEnd(int a[], int left, int right, int k){
	reverse(a, 0, k-1, k);
	reverse(a, 0, n-1, k);
}

// 将数组中的元素循环左移 p(0 < p < n) 个位置
void moveP(int a[], int left, int right, int k){
	reverse(a, 0, p - 1, p);
	reverse(a, p, n - 1, n - p);
	reverse(a, 0, n - 1, n);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值