线性表的相关操作

线性表的物理结构分为顺序存储和链式存储。以下分别是对顺序表和链表的相关操作的代码表示。

 顺序表

一、顺序表的分配 

 1.、顺序表的静态分配

//对顺序表的静态分配
#define MaxSize 100
typedef struct{
	int data[MaxSize];  //使用静态分配的方式
	int length;         //顺序表的当前长度
}SqList;
//初始化一个顺序表
void InitList(SqList &L){
	for(int i = 0; i < MaxSize; i++){
		//对数组中的所有元素进行初始化,虽然不初始化,编译器会自动给数据复制为0,
		//但是存在数组中的元素是系统留下来的脏数据
        //注意for循环里面是MaxSize而不是length
		L.data[i] = 0;
	}
	L.length = 0;
}
#include<iostream>
int main(){
    //在主函数里面检查顺序表是否初始化成功
	SqList L;
	InitList(L);
	for(int i = 0; i < MaxSize; i++){
	cout<<L.data[i];
	
	}
}

2.顺序表的动态分配

//对顺序表的动态分配
#define InitSize 100;  //默认的最大长度
typedef struct{
	int *data;   //指示动态分配数组的指针
	int MaxSize;   //顺序表的最大容量
	int length;    //顺序表的当前长度
}SqList;
//动态增加数组的长度
void IncreaseSize(SqList &L,int len){
    //这里用了引用传递参数
	int *p = L.data;    //建立一个指向数组的指针
	L.MaxSize = InitSize + len;
	L.data = (int *)malloc((L.MaxSize+len)*sizeof(int));  //L.data重新指向了一个新的地址
	for(int i = 0; i < L.length; i++){
		L.data[i] = p[i];  //将数据复制到新的区域
	}
free(q);  //释放原来的内存空间
}

 

二、顺序表的基本操作--插入

 

//顺序表的基本操作--插入
bool ListInsert(SeqList &L,int i, int e){
	//在位序i的位置插入e(位序不同于数组下标,数组下标为”位序-1“)
	
	
	if(i <1 || i > L.length){
		//对于位序是否在合理的范围内进行检查
		//元素要么插在位序为1的位置,要么插入在位序为L.length+1的位置
		return false;
	}

	for(int j = L.length; j>= i; j--){
		L.data[j] = L.data[j-1];
	}
	L.data[i-1] = e;
	L.length ++;
}
return true;

三、顺序表的基本操作--删除

 

//顺序表的基本操作--删除
bool ListDelete(SqList &L,int i,int &e){
	
	//首先检查删除元素的位序是否合理
	if(i < 1 || i > L.length){
		return false;
	}
	
	e = L.data[i-1];
	
	//对数组元素进行前移
	for(int j = i-1; j < L.length-1; j++){
		L.data[j] = L.data[j+1];
	}
	L.length--;
	return true;
}

四、顺序表的基本操作--查找

1.按位查找 (i 表示数据的位置)

int GetElem(SqList &L, int i){
    return L.data[i-1];
}

2.按值查找 

//顺序表的按值查找
int LocateElme(SqList L,int e){
	for(int i = 0;i < L.length; i++){
		if(L.data[i] == e){
		return i+1;
		}
	}
	return 0;
}

链表

一、链表的定义

typedef struct LNode{
	int data;
	struct LNode *next;
}LNode,*LinkList;
//简单说明,LNnode用在定义节点时,LinkList用在定义链表时,功能都差不多,仅仅是为了增加可读性

二、带头节点的链表的初始化

//初始化一个带头节点的单链表
bool InitList1(LinkList &L){
	L = (LinkList)malloc(sizeof(LinkList));  //分配一个头节点

	if(L == NULL){
		//内存不足,分配失败
		return false;
	}

	L->next= NULL;   //头节点之后暂时还没有节点
	return true;
}

三、带头节点的链表的判空

//判断单链表是否为空
bool Empty(LinkList L){
	return (L->next == NULL);
}

四、单链表的建立

1.用头插法建立单链表

注:很多单链表的逆置问题都可以用到头插法

//头插法建立单链表(逆向建立单链表)
LinkList ListHeadInsert(LinkList &L){
	LNode *s;
	int x;
	L->next = NULL;   //只要是初始化单链表都要将头指针指向空,否则L可能
	//会指向一片不知道的内存空间,产生错误
	
	scanf("%d",&x);
	while(x != -1){
		//取一个特殊值结束循环,如-1
		
		s = (LNode *)malloc(sizeof(LNode));
		s->data = x;
		s->next = L->next;     //如果前面没有初始化L,L指向了一个未知的区域
							   //则此时s也会指向一个未知的区域
		L->next =s;
		scanf("%d",&x);
	}
	return L;
}

2.尾插法建立单链表

LinkList ListTailInsert(LinkList &L){
	LNode *s;
	LNode *r; //表尾指针
	int x;
	L->next = NULL;
	r = L;
	scanf("%d",&x);
	while(x != -1){
		s = (LNode *)malloc(sizeof(LNode));
		if(s == NULL){
			printf("内存空间不足!");
		}
		
		s->data = x;
		s->next = r->next;
		r = s;
		scanf("%d",&x);
	}
	r->next = NULL;
	return L;
}

五、带头节点的单链表的基本操作--插入

1.按位插入

//单链表的插入操作--按位序插入
bool ListInsert(LinkList &L,int i,int e){
	if(i < 1){
		return false;
	}
	
	LNode *p;   //指针p指向当前扫描到的节点
	int j = 0;  //记录p指向的是第几个节点(找到插入位置的前一个节点)
	p = L;      //p指向L,头节点认为是第0个节点
	while(p != NULL && j< i-1){
		j++;
		p = p->next;
	}
	
	if(p == NULL){
		return false;  //i的值不合适
	}
	
	LNode *s = (LNode *)malloc(sizeof(LNode));  //申请一个节点放置e
	s->data = e;
	
	//将s节点放在p节点之后
	s->next = p->next;
	p->next = s;
	
	return true;
}

2.指定节点的后插操作--在p节点之后插入元素e

//指定节点的后插操作(在p节点之后插入元素e)
bool InsertNextNode(LNode *p,int e){
	if(p == NULL){
		return false;
	}
	LNode *s = (LNode *)malloc(sizeof(LNode));
	
	//检查内存是否分配成功
	if(s == NULL){
		return false;
	}

	s->data = e;
	
	//插入操作
	s->next = p->next;
	p->next = s;
	return true;
}

 3.在指定节点的前插操作--在p节点之前插入数据元素e

bool InsertPriorNode(LNode *p,int e){
	//这一部分的思想比较巧妙:申请一个节点s,这个节点链接在p节点之后,
	//然后对换节点s和节点p的数据域即可达到前插的效果
	
	LNode *s = (LNode *)malloc(sizeof(LNode));
	if(s == NULL){ 
		//内存分配失败
		return false;
	}
	
	s->next = p->next;
	p->next = s;
	s->data = p->data;
	p->data = e;
	return true;
	
}

六、单链表的删除操作
1。按位序删除(带头节点)
//按位序删除(带头节点)
bool ListDelete(LinkList &L,int i,int &e){
	if(i < 1){
		//位序不合法
		return false;
	}
	
	LNode *p;
	int j = 0;
	p = L;
	while(p != NULL && j < i-1){
		p = p->next;
		j++;
	}
	
	if(p == NULL){
		return false;
	}
	if(p->next == NULL){
		return false;
	}
	LNode *q = p->next;
	p = q->next;
	e = q->data;
	free(q);
	return true;
}

2.指定节点的删除(可以使用双指针,找到前驱节点) 

//指定节点的删除,可以使用双指针
bool ListDelete2(LinkList &L,LNode *p){
	LNode *t,*r;
	t = L;
	if(L->next == NULL){
		return false;
	}
	r = L->next;
	
	if(p == NULL){
		return false;
	}
	
	while(r != p){
		t = r;
		r = r->next;
	}
	t = r->next;
	free(p);
	r->next = NULL;
	return true;
}

上一篇:excel 方框打钩


下一篇:关于线性表中链表的有头单链表实现方式和无头单链表的实现方式