1. 线性表

1.1 线性表的顺序存储

1.1.1 线性表的实现 — 静态分配
功能说明
initSqList(SeqList *L)初始化顺序表
ListInsert(SeqList *L,int i,int e)插入(在顺序表L中的第i个位置插入e)
ListDelete(SeqList *L,int i,int *e)删除(删除顺序表L中的第i个元素并利用传过来的变量 *e 返回删除的数据)
GetElem(SeqList &L,int i)按位查找(查找顺序表L的第i个元素)
LocateElem(SeqList *L, int e)按值查找(在顺序表L中查找e,并返回其位序)
printSeqList(SeqList *L)打印顺序表
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MaxLength 10	// 设置数组的最大长度为 10 

// 定义一个顺序表结构体
typedef struct{
	int data[MaxLength]; 
	int length;		//  记录顺序表当前的长度 
}SeqList;

// 基本功能————初始化顺序表 
void initSeqList(SeqList *L){
	L->length = 0;
} 

// 基本功能————插入(在顺序表L中的第i个位置插入e) 
void ListInsert(SeqList *L,int i,int e){
	if (i<1 || i>L->length + 1){ 
		printf("位序i不合法,插入错误!");
	}else if (L->length >= MaxLength){
		printf("当前存储容量已满,不能插入!");
	}else {
		for(int j = L->length - 1;j >= i - 1;j--)
			L->data[j + 1] = L->data[j];
		L->data[i-1] = e;
		(*L).length++;
		printf("插入成功!\n");
	} 
} 

// 基本功能————删除(删除顺序表L中的第i个元素并利用传过来的变量 *e 返回删除的数据)
int ListDelete(SeqList *L,int i,int *e){
	if (i<1 || i>L->length + 1){ 
		return 0;
	}
	
	*e = L->data[i-1];
	for(int j = i;j<L->length;j++)
		L->data[j-1] = L->data[j];
	(*L).length--;
	return 1;
} 

// 基本功能————按位查找(查找顺序表L的第i个元素) 
int GetElem(SeqList *L,int i){
	if (i<1 || i>L->length + 1){
		printf("不存在该位置的元素!"); 
		return 0;
	}
	return L->data[i - 1];
} 

// 基本功能————按值查找(在顺序表L中查找e,并返回其位序)
int LocateElem(SeqList *L, int e){
	for(int i = 0; i < L->length; i++){
		if(L->data[i] == e)
			return i + 1;
		return 0;
	} 
} 

// 基本功能————打印顺序表 
void printSeqList(SeqList *L){
	// 尝试违规读取顺序表中的所有数据 
//	for(int i = 0;i<MaxLength;i++){
//		printf("data[%d]=%d\n", i, L->data[i]);
//	}
	for(int i = 0;i < L->length;i++){
		printf("data[%d]=%d\n", i, L->data[i]);
	}
}

int main(){
	SeqList L;	// 声明一个顺序表
	initSeqList(&L);	// 初始化顺序表 
	ListInsert(&L,1,100);
	ListInsert(&L,2,98);
	ListInsert(&L,3,50);
	printSeqList(&L);	// 打印顺序表 
	int e = -1;
	if(ListDelete(&L,1,&e) == 1){
		printf("删除的数据为%d\n",e);
	}else{
		printf("位序i不合法,删除错误!");
	}
	
	printf("%d是第%d个数据\n",98,LocateElem(&L , 98));
	
	printSeqList(&L);	// 打印顺序表 
}
1.1.2 线性表的实现 — 动态分配
功能说明
initSeqList(SeqList *L)初始化顺序表
IncreaseSize(SeqList *L, int len)动态添加数组的长度
ListInsert(SeqList *L,int i,int e)插入(在顺序表L中的第i个位置插入e)
ListDelete(SeqList *L,int i,int *e)删除(删除顺序表L中的第i个元素并利用传过来的变量 *e 返回删除的数据)
GetElem(SeqList *L,int i)按位查找(查找顺序表L的第i个元素)
LocateElem(SeqList *L, int e)按值查找(在顺序表L中查找e,并返回其位序)
printSeqList(SeqList *L)打印顺序表
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define InitLength 10	// 设置初始数组的长度为 10 

// 定义一个顺序表结构体
typedef struct {
	int* data;	// 指向动态分配数组的指针 
	int MaxLength;	// 顺序表的最大长度 
	int length;		//  记录顺序表当前的长度 
}SeqList;

// 基本功能————初始化顺序表 
void initSeqList(SeqList *L){
	L->data = (int*)malloc(InitLength * sizeof(int));	// 动态分配数组的空间 (10个)
	L->length = 0;
	L->MaxLength = InitLength;
} 

// 动态添加数组的长度
void IncreaseSize(SeqList *L, int len){
	int* p = L->data;	// 定义一个指针 p 指向指针 data 所指向的位置 
	L->data = (int*)malloc((L->MaxLength+len)*sizeof(int));	// 分配新的内存空间,并让指针 data 指向它
	for(int i = 0 ; i < L->length ; i++){
		// L->data[i] = p[i];	// 将数据复制到新区域 
		*(L->data+i) = *(p + i);	// 与上面的一句话是等价的
		// 理解:
		// 数组 a[] 中 a 就是一个指针,一个指向数组首地址的不能更改的常量指针
		// 所以当一个指针指向数组后,那么相当于这个数组有了一个新的名字
		// 即 a[] 等价于 p[] 
	} 
	L->MaxLength += len;
	free(p);
} 

// 基本功能————插入(在顺序表L中的第i个位置插入e) 
void ListInsert(SeqList *L,int i,int e){
	if (i<1 || i>L->length + 1){ 
		printf("位序i不合法,插入错误!");
	}else if (L->length >= L->MaxLength){
		printf("当前存储容量已满,不能插入!");
	}else {
		for(int j = L->length - 1;j >= i - 1;j--)
			L->data[j + 1] = L->data[j];
		L->data[i-1] = e;
		(*L).length++;
		printf("插入成功!\n");
	} 
} 

// 基本功能————删除(删除顺序表L中的第i个元素并利用传过来的变量 *e 返回删除的数据)
int ListDelete(SeqList *L,int i,int *e){
	if (i<1 || i>L->length + 1){ 
		return 0;
	}
	
	*e = L->data[i-1];
	for(int j = i;j<L->length;j++)
		L->data[j-1] = L->data[j];
	(*L).length--;
	return 1;
} 

// 基本功能————按位查找(查找顺序表L的第i个元素)
int GetElem(SeqList *L,int i) {
	if (i<1 || i>L->length + 1){ 
		return 0;
	}
	return L->data[i - 1];
}

// 基本功能————按值查找(在顺序表L中查找e,并返回其位序)
int LocateElem(SeqList *L, int e){
	for(int i = 0; i < L->length; i++){
		if(L->data[i] == e)
			return i + 1;
		return 0;
	} 
} 

// 基本功能————打印顺序表 
void printSeqList(SeqList *L){
	// 尝试违规读取顺序表中的所有数据 
//	for(int i = 0;i<L->MaxLength;i++){
//		printf("data[%d]=%d\n", i, L->data[i]);
//	}
	for(int i = 0;i < L->length;i++){
		printf("data[%d]=%d\n", i, L->data[i]);
	}
}

int main(){
	SeqList L;	// 声明一个顺序表
	initSeqList(&L);	// 初始化顺序表 
	IncreaseSize(&L , 5);	// 扩容
	
	ListInsert(&L , 1 , 123);	// 插入数据 
	ListInsert(&L , 2 , 78);
	ListInsert(&L , 3 , 98);
	
	int e = -1;	// 删除元素
	ListDelete(&L , 2 , &e);
	printf("删除的元素是:%d\n", e);
	 
	printSeqList(&L);	// 打印顺序表 
}

1.2 线性表的链式存储

1.2.1 单链表
1.2.1.1 带头节点的单链表
功能说明
InitList(LinkList *L)初始化**(有区别)**
Empty(LinkList L)判断单链表是否为空**(有区别)**
ListInsert(LinkList L, int i, int e)按位序插入(在 L 的第 i 个节点插入元素 e)(有区别)
ListDelete(LinkList L, int i)按位序删除(删除表 L 中的第 i 个节点的元素)(有区别)
GetElem(LinkList L, int i)按位查找(返回表 L 中的第 i 个节点的元素)(有区别)
LocateElem(LinkList L, int e)按值查找(返回表 L 中的存储着e的元素)(有区别)
Length(LinkList L)求表的长度**(有区别)**
PrintList(LinkList L)打印单链表
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct LNode{	// 定义一个单链表的节点类型 
	int data;	// 每个节点的数据域 
	struct LNode* next;	// 每个节点的指针域,指针指向下一个节点 
}LNode, *LinkList;
// LNode* 强调的是节点		LinkList 强调的是单链表 

// 初始化(带头节点)
void InitList(LinkList *L){ 
	*L = (LNode*)malloc(sizeof(LNode));	// 分配一个头节点 (头节点是不存储数据的)
	if(*L == NULL){
		printf("分配空间失败!\n");
	}else{
		(*L)->next = NULL;
		printf("分配空间成功!\n");
	}
}

// 判断单链表是否为空(带头节点) 
void Empty(LinkList L){
	if (L->next == NULL){
		printf("单链表为空!\n");
	}else{
		printf("单链表不为空!\n");
	}
}

// 按位序插入(带头节点)
// 在 L 的第 i 个节点插入元素 e 
void ListInsert(LinkList L, int i, int e){
	// 如果要插入的位置小于1则报错 
	if(i<1){
		printf("位序i不合法,插入错误!");
		exit(1); 
	}
	LNode* p = L;	// 指针p指向当前扫描到的节点(初始化指向第一个节点) 
	int j = 0; 	// 记录当前p指向的是第几个节点
	
	while(p != NULL && j < i - 1){	// 找到插入的位置 
		p = p->next;
		j++;
	} 
	
	// 如果要插入的位置大于 L 的实际长度,则报错 
	if (p == NULL){
		printf("位序i不合法,插入错误!");
		exit(1);
	} 
	LNode* s = (LNode*)malloc(sizeof(LNode)); 
	if (s == NULL){
		printf("分配空间失败!!!");
		exit(1); 
	}
	s->data = e;	// 插入元素 
	s->next = p->next;
	p->next = s;
	printf("插入成功!\n");
} 

// 按位序删除(带头节点)
// 删除表 L 中的第 i 个节点的元素
void ListDelete(LinkList L, int i){
	// 如果要删除的位置小于1则报错 
	if(i<1){
		printf("位序i不合法,删除错误!");
		exit(1); 
	}
	LNode* p = L;	// 指针p指向当前扫描到的节点(初始化指向第一个节点) 
	int j = 0; 	// 记录当前p指向的是第几个节点
	
	while(p != NULL && j < i - 1){	// 找要删除的元素的前一个节点 
		p = p->next;
		j++;
	} 
	
	// 如果要删除的位置大于 L 的实际长度,则报错 
	if (p == NULL || p->next == NULL){
		printf("位序i不合法,删除错误!");
		exit(1);
	}
	
	LNode* q = p->next; 	// 定义一个指针指向要删除的节点
	p->next = q->next;
	free(q); 
	printf("删除成功!\n");
} 

// 按位序查找(带头节点)
// 返回表 L 中的第 i 个节点的元素
LNode* GetElem(LinkList L, int i){
	// 如果要查找的位置小于1则报错 
	if(i<1){
		printf("查找的位置不正确!");
		exit(1); 
	}
	LNode* p = L;	// 指针p指向当前扫描到的节点(初始化指向第一个节点) 
	int j = 0; 	// 记录当前p指向的是第几个节点
	
	while(p != NULL && j < i){	// 找到第i个节点 
		p = p->next;
		j++;
	} 
	return p;
} 

// 按值查找(带头节点)
// 返回表 L 中的存储着e的元素
LNode* LocateElem(LinkList L, int e){
	LNode* p = L->next;	// 指针p指向第一个节点 
	
	while(p != NULL && p->data != e){	// 当找到或未找到(p指向NULL)时停下 
		p = p->next;
	} 
	return p;
} 

// 求表的长度(带头节点)
int Length(LinkList L){
	int len = 0;
	LNode* p = L;
	while(p->next != NULL){
		p = p->next;
		len++;
	}
	return len;
} 

// 打印单链表
void PrintList(LinkList L){
	LNode* p = L->next;		// p指向实际存储数据的第一个节点 
	while(p != NULL){
		printf("%d\n",p->data);
		p = p->next; 
	}
} 

void main(){
	LinkList L;		// 声明一个指向单链表的指针
	InitList(&L); 
	
	Empty(L); 
	ListInsert(L ,1 ,78);
	ListInsert(L ,2 ,48);
	ListInsert(L ,3 ,12345);
	
	PrintList(L);
	ListDelete(L ,2);
	PrintList(L);
	
}
1.2.1.2 不带头结点的单链表
功能说明
InitList(LinkList *L)初始化**(有区别)**
Empty(LinkList L)判断单链表是否为空**(有区别)**
ListInsert(LinkList L, int i, int e)按位序插入(在 L 的第 i 个节点插入元素 e)(有区别)
PrintList(LinkList L)打印单链表
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct LNode{	// 定义一个单链表的节点类型 
	int data;	// 每个节点的数据域 
	struct LNode* next;	// 每个节点的指针域,指针指向下一个节点 
}LNode, *LinkList;
// LNode* 强调的是节点		LinkList 强调的是单链表 

// 初始化(不带头节点) 
void InitList(LinkList *L){
	*L = NULL;	// 空表,没有任何节点 
}

// 判断单链表是否为空(不带头节点) 
int Empty(LinkList L){
	if (L == NULL){
		printf("单链表为空!");
	}else{
		printf("单链表不为空!");
	}
} 

// 按位序插入(不带头节点) 
// 在 L 的第 i 个节点插入元素 e 
void ListInsert(LinkList* L, int i, int e){
	// 如果要插入的位置小于1则报错 
	if(i<1){
		printf("位序i不合法,插入错误!");
		exit(1); 
	}else if(i == 1){
		LNode* s = (LNode*)malloc(sizeof(LNode));
		s->data = e;
		s->next = *L;
		*L = s;
		printf("插入成功!\n");
		return;
	} 
	LNode* p = *L;	// 指针p指向当前扫描到的节点(初始化指向第一个节点) 
	int j = 1; 	// 记录当前p指向的是第几个节点
	
	while(p != NULL && j < i - 1){	// 找到插入的位置 
		p = p->next;
		j++;
	} 
	
	// 如果要插入的位置大于 L 的实际长度,则报错 
	if (p == NULL){
		printf("位序i不合法,插入错误!");
		exit(1);
	} 
	LNode* s = (LNode*)malloc(sizeof(LNode)); 
	if (s == NULL){
		printf("分配空间失败!!!");
		exit(1); 
	}
	s->data = e;	// 插入元素 
	s->next = p->next;
	p->next = s;
	printf("插入成功!!\n");
} 

// 打印单链表
void PrintList(LinkList L){
	while(L != NULL){
		printf("%d\n",L->data);
		L = L->next; 
	}
} 

void main(){
	LinkList L;		// 声明一个指向单链表的指针
	InitList(&L); 
	
	ListInsert(&L ,1 ,78);
	ListInsert(&L ,2 ,48);
	ListInsert(&L ,3 ,12345);
	
	PrintList(L);
}
1.2.1.3 前插操作

没有区别 带/不带 头节点都适用

// 前插操作:在p节点之前插入元素e
void InsertPriorNode(LNode* p, int e){
	if (p == NULL){
		printf("插入失败!");
	}
	LNode* s = (LNode*)malloc(sizeof(LNode));
	if (s == NULL){
		printf("分配空间失败!");
	} 
	s->data = p->data;
	s->next = p->next;
	p->next = s;
	p->data = e;
	printf("插入成功!\n");
} 
1.2.1.4 后插操作

没有区别 带/不带 头节点都适用

// 后插操作:在p节点之后插入e 
void InsertNextNode(LNode* p, int e){
	if (p == NULL){
		printf("插入失败!");
	}
	LNode* s = (LNode*)malloc(sizeof(LNode));
	if (s == NULL){
		printf("分配空间失败!");
	} 
	s->data = e;
	s->next = p->next;
	p->next = s;
	printf("插入成功!\n");
} 
1.2.1.5 删除指定节点(有bug)

如果删除的是最后一个节点的话,将会无法删除(程序不会报错,但也不会达到预期目的)

(可能会想,我单独将这一种情况进行判断不就好了吗?注意:删除最后一个节点,就是将该节点的前驱指向NULL,请问能实现吗?(直接free掉最后一个节点是不行的))

// 删除指定的节点
void DeleteNode(LNode* p){
	if (p == NULL){
		printf("删除失败!\n");
	}
	LNode* q = p->next;		// 定义一个指针q指向要删除的节点的后继节点 
	p->data = q->data;		// 将后继节点的数据赋值给要删除的节点 
	p->next = q->next;		// 让要删除的节点指向后继节点的后继节点
	free(q);	// 释放后继节点的存储空间 
	printf("删除成功!\n"); 
} 
1.2.1.6 单链表的建立

1.2.1.6.1 头插法

LinkList CreatListHead(){
	LinkList L = (LNode*)malloc(sizeof(LNode));		// 头节点
	if (L == NULL){
		printf("分配空间失败!!!");
		exit(1); 
	} 
	L->next = NULL;	// 如果不初始化,可能会有脏数据,即指向一个未知的区域 
	LNode* s;	// 用于暂存需要添加的数据 
	int x = 0;
	printf("请输入你想要添加的数据:");
	scanf("%d", &x); 
	while(x != 9999){	// 输入9999表示结束 
		s = (LNode*)malloc(sizeof(LNode)); 
		if (s == NULL){
			printf("分配空间失败!!!");
			exit(1); 
		} 
		s->data = x;
		s->next = L->next;
		L->next = s;
		printf("请输入你想要添加的数据:");
		scanf("%d", &x);
	}
	return L;
}

1.2.1.6.2 尾插法

LinkList CreatListTail(){
	LinkList L = (LNode*)malloc(sizeof(LNode));		// 头节点
	if (L == NULL){
		printf("分配空间失败!!!");
		exit(1); 
	} 
	L->next = NULL;	// 初始化 
	LNode* s;	// 用于暂存需要添加的数据 
	LNode* r = L;	// r永远指向尾部,即尾指针
	int x = 0;
	printf("请输入你想要添加的数据:");
	scanf("%d", &x); 
	while(x != 9999){	// 输入9999表示结束 
		s = (LNode*)malloc(sizeof(LNode)); 
		if (s == NULL){
			printf("分配空间失败!!!");
			exit(1); 
		} 
		s->data = x;
		s->next = r->next;
		r->next = s;
		r = s;	// 尾指针指向最后一个节点
		printf("请输入你想要添加的数据:");
		scanf("%d", &x);
	}
	return L;
}
1.2.2 双链表
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct DNode{	// 定义一个双链表的节点类型 
	int data;	// 每个节点的数据域 
	struct DNode* prior,* next;	// 前驱和后继指针 
}DNode, *DLinkList;

// 初始化(带头节点)
void DInitList(DLinkList *L){ 
	*L = (DNode*)malloc(sizeof(DNode));	// 分配一个头节点 (头节点是不存储数据的)
	if(*L == NULL){
		printf("分配空间失败!\n");
	}else{
		(*L)->next = NULL;
		(*L)->prior = NULL;
		printf("分配空间成功!\n");
	}
}

// 判断双链表是否为空(带头节点) 
void Empty(DLinkList L){
	if (L->next == NULL){
		printf("单链表为空!\n");
	}else{
		printf("单链表不为空!\n");
	}
}

// 按位序插入(带头节点)
// 在 L 的第 i 个节点后插入元素 e 
void DListInsert(DLinkList L, int i, int e){
	// 如果要插入的位置小于1则报错 
	if(i<1){
		printf("位序i不合法,插入错误!");
		exit(1); 
	}
	DNode* p = L;	// 指针p指向当前扫描到的节点(初始化指向第一个节点) 
	int j = 0; 	// 记录当前p指向的是第几个节点
	
	while(p != NULL && j < i - 1){	// 找到插入的位置 
		p = p->next;
		j++;
	} 
	
	// 如果要插入的位置大于 L 的实际长度,则报错 
	if (p == NULL){
		printf("位序i不合法,插入错误!");
		exit(1);
	} 
	DNode* s = (DNode*)malloc(sizeof(DNode)); 
	if (s == NULL){
		printf("分配空间失败!!!");
		exit(1); 
	}
	s->data = e;
	s->next = p->next;	// 插入元素 
	if(p->next != NULL)
		p->next->prior = s->next;
	s->prior = p->next;
	p->next = s;
	printf("插入成功!\n");
} 

// 按位序删除(带头节点)
// 删除表 L 中的第 i 个节点的元素
void DListDelete(DLinkList L, int i){
	// 如果要删除的位置小于1则报错 
	if(i<1){
		printf("位序i不合法,删除错误!");
		exit(1); 
	}
	DNode* p = L;	// 指针p指向当前扫描到的节点(初始化指向第一个节点) 
	int j = 0; 	// 记录当前p指向的是第几个节点
	
	while(p != NULL && j < i - 1){	// 找要删除的元素的前一个节点 
		p = p->next;
		j++;
	} 
	
	// 如果要删除的位置大于 L 的实际长度,则报错 
	if (p == NULL || p->next == NULL){
		printf("位序i不合法,删除错误!");
		exit(1);
	}
	
	DNode* q = p->next; // 定义一个指针指向要删除的节点
	p->next = q->next;
	if(q->next!=NULL){
		p->next->prior = p;
	}
	free(q); 
	printf("删除成功!\n");
} 

// 打印双链表
void DPrintList(DLinkList L){
	DNode* p = L->next;		// p指向实际存储数据的第一个节点 
	while(p != NULL){
		printf("%d\n",p->data);
		p = p->next; 
	}
} 

void main(){
	DLinkList L;	// 声明一个指向双链表的指针
	DInitList(&L); 
	
	DListInsert(L ,1 ,78);
	DListInsert(L ,2 ,48);
	DListInsert(L ,3 ,12345);
	
	DPrintList(L);
	DListDelete(L ,2);
	DPrintList(L);
	
}
1.2.3 双向链表
1.2.3.1 循环单链表
#include <stdio.h>
#include <stdlib.h>

typedef struct LNode {    // 定义一个单链表的节点类型
    int data;    // 每个节点的数据域
    struct LNode *next;    // 每个节点的指针域,指针指向下一个节点
} LNode, *LinkList;

// 初始化循环单链表(带头节点)
void InitList(LinkList *L) {
    *L = (LNode *) malloc(sizeof(LNode));    // 分配一个头节点 (头节点是不存储数据的)
    if (*L == NULL) {
        printf("分配空间失败!\n");
    } else {
        (*L)->next = *L;
        printf("分配空间成功!\n");
    }
}

// 判断循环单链表是否为空(带头节点)
void Empty(LinkList L) {
    if (L->next == L) {
        printf("单链表为空!\n");
    } else {
        printf("单链表不为空!\n");
    }
}

// 求表的长度(带头节点)
int Length(LinkList L) {
    int len = 0;
    LNode *p = L;
    while (p->next != L) {
        p = p->next;
        len++;
    }
    return len;
}

// 按位序插入(带头节点)
// 在 L 的第 i 个节点插入元素 e
void ListInsert(LinkList L, int i, int e) {
    // 如果要插入的位置小于1或者超出最大长度则报错
    if (i < 1) {
        printf("位序i不合法,插入错误!");
        exit(1);
    }

    if (i == 1) {
        LNode *s = (LNode *) malloc(sizeof(LNode));
        if (s == NULL) {
            printf("分配空间失败!!!");
            exit(1);
        }
        s->data = e;    // 插入元素
        s->next = L;
        L->next = s;
        printf("插入成功!\n");
    } else {
        LNode *p = L->next;    // 指针p指向当前扫描到的节点(初始化指向第一个节点)
        int j = 1;    // 记录当前p指向的是第几个节点

        while (p != L && j < i - 1) {    // 找到插入的位置
            p = p->next;
            j++;
        }

        // 如果要插入的位置大于 L 的实际长度,则报错
        if (p == L) {
            printf("位序i超过了循环单链表的最大长度,插入错误!");
            exit(1);
        }

        LNode *s = (LNode *) malloc(sizeof(LNode));
        if (s == NULL) {
            printf("分配空间失败!!!");
            exit(1);
        }
        s->data = e;    // 插入元素
        s->next = p->next;
        p->next = s;
        printf("插入成功!\n");
    }
}

// 按位序删除(带头节点)
// 删除表 L 中的第 i 个节点的元素
void ListDelete(LinkList L, int i) {
    // 如果要删除的位置小于1则报错
    if (i < 1) {
        printf("位序i不合法,删除错误!");
        exit(1);
    }
    LNode *p = L->next;    // 指针p指向当前扫描到的节点(初始化指向第一个节点)
    int j = 1;    // 记录当前p指向的是第几个节点

    while (p != L && j < i - 1) {    // 找要删除的元素的前一个节点
        p = p->next;
        j++;
    }

    // 如果要删除的位置大于 L 的实际长度,则报错
    if (p == L) {
        printf("位序i不合法,删除错误!");
        exit(1);
    }

    LNode *q = p->next;    // 定义一个指针指向要删除的节点
    p->next = q->next;
    free(q);
    printf("删除成功!\n");
}

// 按位序查找(带头节点)
// 返回表 L 中的第 i 个节点的元素
LNode *GetElem(LinkList L, int i) {
    // 如果要查找的位置小于1则报错
    if (i < 1) {
        printf("查找的位置不正确!");
        exit(1);
    }
    LNode *p = L->next;    // 指针p指向当前扫描到的节点(初始化指向第一个节点)
    int j = 1;    // 记录当前p指向的是第几个节点

    while (p != L && j < i) {    // 找到第i个节点
        p = p->next;
        j++;
    }
    return p;
}

// 按值查找(带头节点)
// 返回表 L 中的存储着e的元素
LNode *LocateElem(LinkList L, int e) {
    LNode *p = L->next;    // 指针p指向第一个节点

    while (p != L && p->data != e) {    // 当找到或未找到(p指向NULL)时停下
        p = p->next;
    }
    return p;
}

// 打印循环单链表
void PrintList(LinkList L) {
    LNode *p = L->next;        // p指向实际存储数据的第一个节点
    while (p != L) {
        printf("%d\n", p->data);
        p = p->next;
    }
}

void main() {
    LinkList L;        // 声明一个指向单链表的指针
    InitList(&L);

    Empty(L);
//    ListDelete(L, 1);   // 按位序删除
    ListInsert(L, 1, 78);
    ListInsert(L, 2, 48);
    ListInsert(L, 2, 12345);
    printf("%d\n", Length(L));
    printf("%d\n", LocateElem(L, 12345)->data);     // 按值查找
    printf("第2个元素为:%d\n", GetElem(L, 2)->data);  // 安位序查找

    PrintList(L);
    ListDelete(L, 2);   // 按位序删除
    PrintList(L);
}
1.2.3.2 循环双链表

1.3 线性表的销毁

如果线性表是用数组实现的,那么将不需要手动回收,系统会自动回收。

如果线性表是使用了malloc函数实现的,那么将需要手动回收(free函数)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是基于数组实现的线性表的基本操作及应用的 C++ 代码示例: ```c++ #include <iostream> #define MAXSIZE 100 // 线性表最大长度 using namespace std; typedef struct { int data[MAXSIZE]; // 数组存储元素,从下标 1 开始存储 int length; // 线性表当前长度 } SqList; // 初始化线性表 void InitList(SqList &L) { L.length = 0; } // 插入元素 bool InsertList(SqList &L, int i, int x) { if (i < 1 || i > L.length + 1 || L.length >= MAXSIZE) { return false; } for (int j = L.length; j >= i; j--) { L.data[j + 1] = L.data[j]; } L.data[i] = x; L.length++; return true; } // 删除元素 bool DeleteList(SqList &L, int i) { if (i < 1 || i > L.length) { return false; } for (int j = i; j < L.length; j++) { L.data[j] = L.data[j + 1]; } L.length--; return true; } // 查找元素 int SearchList(SqList L, int x) { for (int i = 1; i <= L.length; i++) { if (L.data[i] == x) { return i; } } return -1; } // 输出线性表 void PrintList(SqList L) { for (int i = 1; i <= L.length; i++) { cout << L.data[i] << " "; } cout << endl; } int main() { SqList L; InitList(L); InsertList(L, 1, 1); InsertList(L, 2, 2); InsertList(L, 3, 3); PrintList(L); DeleteList(L, 2); PrintList(L); int pos = SearchList(L, 3); cout << "3 is at position " << pos << endl; return 0; } ``` 以上代码实现了线性表的创建、插入、删除、查找等基本操作,并提供了一个输出线性表的函数。在 main 函数中,首先创建了线性表 L,然后插入了三个元素,输出线性表,接着删除了第二个元素,再次输出线性表,最后查找元素 3 在线性表中的位置,并输出结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BUG_GUB

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值