线性表的基本操作(初始化、创建、增、删、查)

目录

顺序表

顺序表的定义和初始化

顺序表的基本操作

1.求表长

2.判空操作

3.创建顺序表

4.输出操作

5.插入操作

6.删除操作

7.按位查找操作

8.按值查找操作

单链表

单链表的定义

单链表的初始化

求表长

判空操作

 尾插法建立单链表

头插法建立单链表

输出操作

前插操作

后插操作

插入结点操作

按位查找

删除位序i的节点

指定结点删除


顺序表

线性表的顺序存储又称顺序表。它是用一组地址连续的存储单元依次存储线性表中的数据元素,从而使得逻辑上相邻的两个元素在物理位置上也相邻

第1个元素存储在线性表的起始位置,第i个元素的存储位置后面紧接着存储的是第i+1个元素,称 i为线性表中的位序

顺序表的定义和初始化

#define _CRT_SECURE_NO_WARNINGS

#include<stdlib.h>
#include<stdio.h>
#include<iostream>

using namespace std;

//顺序表

/*
//静态分配
#define MaxSize 50       //定义顺序表的最大长度

typedef struct {         
	int data[MaxSize];   //顺序表的元素
	int length;          //顺序表的当前长度
}Sqlist;                 //顺序表的类型定义

// 静态顺序表的初始化
void InitList_1(Sqlist& L) {
	L.length = 0;
	printf("顺序表初始化完成\n");
}
*/

//动态分配
#define InitSize 100     //表长度的初始定义

typedef struct {
	int* data;
	int MaxSize, length;
}Sqlist;

//动态顺序表初始化
void Initlist(Sqlist& L) {
	
	//L.data = (int*)malloc(sizeof(int) * InitSize);    //C语言动态分配

	L.data = new int(InitSize);  //C++动态分配
	L.length = 0;
	L.MaxSize = InitSize;
	printf("顺序表初始化完成\n");
}

一维数组静态分配时,由于数组的大小和空间事先已经固定,一旦空间占满,再加入新的数据就会产生溢出,进而导致程序崩溃。

而在动态分配时,存储数组的空间是在程序执行过程中通过动态存储分配语句分配的,一旦数据空间占满,就另外开辟一块更大的存储空间,用以替换原来的存储空间,从而达到扩充存储数组空间的目的,而不需要为线性表一次性地划分所有空间。 

注意:动态分配并不是链式存储,它同样属于顺序存储结构,物理结构没有变化,依然是随机存取方式,只是分配的空间大小可以在运行时动态决定。


顺序表的基本操作

1.求表长

//求表长:返回线性表工的长度,即L中数据元素的个数
int Length(Sqlist L) {
	return L.length;
}

2.判空操作

//判空操作:若L为空表,则返回true,否则返回false
bool Empty(Sqlist L) {
	if (L.length == 0)
		return true;
	else
		return false;
}

3.创建顺序表

//创建顺序表:传值
void CreatList(Sqlist &L) {
	int n;
	printf("请传入顺序表数值个数:");
	scanf("%d", &n);
	printf("请输入顺序表数值:");
	for (int i = 0; i < n; i++)
	{
		cin >> L.data[i];
		L.length++;
	}
}

4.输出操作

//输出操作:打印顺序表
void PrintList(Sqlist L) {
	printf("目前顺序表的数据元素为:");
	for (int i = 0; i < L.length; i++)
		printf("%d ", L.data[i]);
	printf("\n");
}

5.插入操作

//插入操作:顺序表的第i个位置插入新元素e
bool ListInsert(Sqlist& L, int i, int e) {
	if (i<1 || i>L.length + 1)             //判断i的范围是否有效
		return false;
	if (L.length >= L.MaxSize)             //若存储空间已满,不能插入
		return false;
	for (int j = L.length; j >= i; j--) {  //将第i个元素及之后的元素后移
		L.data[j] = L.data[j - 1];
	}
	L.data[i-1] = e;                       //在位置i处放入e
	L.length++;                            //顺序表长 + 1
	return true;

}

6.删除操作

//删除操作:删除顺序表L中第i个位置的元素,用引用变量e返回
bool ListDelete(Sqlist& L, int i, int& e) {
	if (i<1 || i>L.length)                 //判断i的范围是否有效
		return false;
	e = L.data[i - 1];                     //被删除的元素赋值给e
	for (int j = i; j < L.length; j++)     //将第i个元素之后的元素前移
		L.data[i - 1] = L.data[i];
	L.length--;                            //顺序表长 - 1
	return true;
}

7.按位查找操作

//按位查找操作:获取表L中第i个位置的元素的值
int GetElem(Sqlist L, int i) {
	if (i<1 || i>L.length)                 //判断i的范围是否有效
		return 0;
	return L.data[i - 1];
}

8.按值查找操作

//按值查找操作:在表L中查找第一个等于给定关键字值的元素,返回其位序
int LocateElem(Sqlist L, int e) {
	for (int i = 0; i < L.length; i++) {
		if (L.data[i] == e)
			return i + 1;
	}
	return 0;                              //未找到,返回0
}



单链表

线性表的链式存储又称单链表,它是指通过一组任意的存储单元来存储线性表中的数据元素。为了建立数据元素之间的线性关系,对每个链表结点,除存放元素自身的信息外,还需要存放一个指向其后继的指针

通常用头指针来标识一个单链表,如单链表L。为了操作上的方便,在单链表第一个结点之前附加一个结点,称为头结点。头结点的数据域可以不设任何信息,也可以记录表长等信息。头结点的指针域指向线性表的第一个元素结点

头结点和头指针的区分:不管带不带头结点,头指针都始终指向链表的第一个结点,而头结点是带头结点的链表中的第一个结点,结点内通常不存储信息

单链表的定义

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


//struct LNode*  == LinkList
//强调节点  用LNode
//强调链表  用LinkList
//

单链表的初始化

//单链表初始化(不带头结点)
void InitLink(LinkList& L) {
	L = NULL;
	printf("单链表初始化完成\n");
}

//单链表初始化(带头结点)
void InitLink_1(LinkList& L) {
	L = (LinkList)malloc(sizeof(LNode));
	if (L == NULL)
		printf("单链表初始化失败");
	else {
		L->next = NULL;
		printf("单链表初始化完成");
	}
}

求表长

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


//求单链表长度(带头结点不包括头结点)
int Length(LinkList L) {
	int len = 0;
	LNode* p = L->next;
	while (p) {
		len++;
		p = p->next;
	}
	return len;
}

判空操作

//判空操作(不带头结点)
bool Empty(LinkList L) {
	if (L == NULL)
		return true;
	else
		return false;
}

//判空操作(带头结点)
bool Empty_1(LinkList L) {
	if (L->next == NULL)
		return true;
	else
		return false;
}

 尾插法建立单链表

//尾插法建立单链表(不带头结点)
LinkList List_TailInsert(LinkList& L) {
	int x;
	printf("尾插法输入数据元素(以-1作为输入结束)\n");
	cin >> x;
	if (x != -1) {
		L = new LNode;                //先创建第一个数据元素结点(作用似头结点)
		L->data = x;                  //下面同带头结点
		LNode* s, * r = L;
		cin >> x;
		while (x != -1) {
			s = new LNode;
			s->data = x;
			s->next = NULL;
 			r->next = s;
			r = s;
			cin >> x;
		}
	}
	
	return L;
}

//尾插法建立单链表(带头结点)
LinkList List_TailInsert_1(LinkList& L) {
	L = new LNode;                         //创建头结点
	LNode* s, * r = L;                     //r为尾指针
	int x;
	printf("尾插法输入数据元素(以-1作为输入结束)\n");
	cin >> x;
	while (x != -1) {
		s = new LNode;                 
		s->data = x;
		s->next = NULL;                    //尾结点指向NULL
		r->next = s;                       //插入新结点
		r = s;                             //更新尾指针
		cin >> x;
	}
	return L;
}

头插法建立单链表

//头插法建立单链表(不带头结点)
LinkList List_HeadInsert(LinkList& L) {
	LNode* s;
	int x;
	printf("头插法输入数据元素(以-1作为输入结束)\n");
	cin >> x;
	while (x != -1) {
		s = (LNode*)malloc(sizeof(LNode));
		s->data = x;
		s->next = L;
		L = s;
		cin >> x;
	}
	return L;
}

//头插法建立单链表(带头结点)
LinkList List_HeadInsert_1(LinkList& L) {
	int x;
	LNode* s;
	L = (LinkList)malloc(sizeof(LNode));
	L->next = NULL;
	printf("头插法输入数据元素(以-1作为输入结束)\n");
	cin >> x;
	while (x != -1) {
		s = (LNode*)malloc(sizeof(LNode));
		s->data = x;
		s->next = L->next;
		L->next = s;
		cin >> x;
	}
	return L;
}

输出操作

//输出操作:打印单链表(不带头结点)
void PrintLink(LinkList L) {
	LNode* p = L;
	while (p) {
		printf("%d ", p->data);
		p = p->next;
	}
	printf("\n");
}

//输出操作:打印单链表(带头结点)
void PrintLink_1(LinkList L) {
	LNode* p = L->next;            //不打印头结点
	while (p) {
		printf("%d ", p->data);
		p = p->next;
	}
	printf("\n");
}

前插操作

//前插操作,在结点p前插入元素e
bool InsertPriorNode(LNode* p, int e) {
	if (!p) 
        return false;
	LNode* s = (LNode*)malloc(sizeof(LNode));
	if (!s) 
        return false;
	s->next = p->next;                     //将*s结点插入到*p结点之前
	p->next = s;
	s->data = p->data;
	p->data = e;
	return true;
}

后插操作

//后插操作,在结点p之后插入元素e
bool InsertNextNode(LNode* p, int e) {
	if (!p) 
        return false;
	LNode* s = (LNode*)malloc(sizeof(LNode));
	if (!s) 
        return false;
	s->data = e;                        //将*s结点插入到*p结点之后
	s->next = p->next;               
	p->next = s;
	return true;
}

插入结点操作

//插入结点操作(不带头结点)
bool LinkInsert(LinkList& L, int i, int e) {
	if (i < 1) return false;
	if (i == 1) {
		LNode* s = (LNode*)malloc(sizeof(LNode));
		s->data = e;
		s->next = L;
		L = s;
		return true;
	}
	LNode* p = L;
	int j = 1;
	while (p!= NULL && j < i - 1)         //循环找到第i-1个结点 = GetElem(L, i-1);
	{                                     //LNode* p = GetElem(L, i-1);
		p = p->next;
		j++;
	}
	if (p == NULL)                          //i值不合法
		return false;
	LNode* s = (LNode*)malloc(sizeof(LNode));
	s->data = e;
	s->next = p->next;
	p->next = s;                           //插入结点s到p之后 
	return true;
}

//插入结点操作(带头结点)
bool LinkInsert_1(LinkList& L, int i, int e) {
	if (i < 1) return false;
	LNode* p = L;
	int j = 0;
	while (p != NULL && j < i - 1)         //循环找到第i-1个结点 = GetElem_1(L, i-1);
	{
		p = p->next;
		j++;
	}
	if (p == NULL)                          //i值不合法
		return false;
	LNode* s = (LNode*)malloc(sizeof(LNode));
	s->data = e;
	s->next = p->next;
	p->next = s;                           //插入结点s到p之后 
	return true;
}

按位查找

//按位查找,返回第i个数据结点(不带头结点)
LNode* GetElem(LinkList L, int i) {
	if (i < 1)
		return NULL;
	int j = 1;
	LNode* p = L;
	while (p && j < i) {
		p = p->next;
		j++;
	}
	return p;
}

//按位查找,返回第i个数据结点(带头结点)
LNode* GetElem_1(LinkList L, int i) {
	if (i < 0)                             //i=0表示头结点
		return NULL;
	int j = 0;
	LNode* p = L;
	while (p && j < i) {
		p = p->next;
		j++;
	}
	return p;
}

按值查找

//按值查找,找到数据域等于e的结点(不带头结点)
LNode* LocateElem(LinkList L, int e) {
	LNode* p = L;
	while (p) {                            //找到返回p
		if (p->data == e)
			return p;
		p = p->next;
	}
	return NULL;                          //找不到返回NULL
}

//按值查找,找到数据域等于e的结点(带头结点)
LNode* LocateElem_1(LinkList L, int e) {
	LNode* p = L->next;
	while (p) {
		if (p->data == e)
			return p;
		p = p->next;
	}
	return NULL;
}

删除位序i的节点

//删除位序i的节点,用e返回该结点的值(不带头结点)
bool LiskDelete(LinkList& L, int i, int& e) {
	if (L == NULL) {                         //空表
		e = -1;
		return false;
	}
	if (i < 1) 
		return false;
	else if (i > 1) {
		LNode* p = GetElem(L, i - 1);         //按位序查找找到要删除的前一个结点
		if (p == NULL) return false;          //i值不合法 
		if (p->next == NULL) return false;    //第i-1个节点之后没有其他节点 
		LNode* q = p->next;                   
		e = q->data;
		p->next = q->next;                    //删除结点q
		free(q);
	}
	else {
		if (L->next == NULL) {                //i=1 && L只有一个结点
			e = L->data;
			L = NULL;
		}
		else {                                //i=1 && L不只一个结点
			e = L->data;
			L = L->next;
		}
	}
	return true;
}

//删除位序i的节点,用e返回该结点的值(带头结点)
bool LiskDelete_1(LinkList& L, int i, int& e) {
	if (i < 1) 
		return false;
	LNode* p = GetElem(L, i - 1);         //按位序查找找到要删除的前一个结点
	if (p == NULL) return false;          //i值不合法 
	if (p->next == NULL) return false;    //第i-1个节点之后没有其他节点 
	LNode* q = p->next;
	e = q->data;
	p->next = q->next;
	free(q);
	return true;
}

 指定结点删除

//指定结点删除
bool DeleteNode(LNode* p) {
	if (p == NULL) 
		return false;
	LNode* q = p->next;                    //q指向*p的后继节点 
	p->data = p->next->data;               //p的后继节点数据赋值给p 
	p->next = q->next;                     //q节点从链中断开 
	free(q);                               //释放 
	return true;
}

  • 35
    点赞
  • 242
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是Python实现的线性表顺序存储初始化的代码: ``` class SqList: def __init__(self, max_size): self.max_size = max_size self.length = 0 self.data = [None] * max_size def is_empty(self): return self.length == 0 def is_full(self): return self.length == self.max_size def append(self, value): if self.is_full(): raise Exception("List is full") self.data[self.length] = value self.length += 1 def insert(self, index, value): if self.is_full(): raise Exception("List is full") if index < 0 or index > self.length: raise Exception("Index out of range") for i in range(self.length, index, -1): self.data[i] = self.data[i-1] self.data[index] = value self.length += 1 def delete(self, index): if self.is_empty(): raise Exception("List is empty") if index < 0 or index >= self.length: raise Exception("Index out of range") for i in range(index, self.length-1): self.data[i] = self.data[i+1] self.length -= 1 def get(self, index): if self.is_empty(): raise Exception("List is empty") if index < 0 or index >= self.length: raise Exception("Index out of range") return self.data[index] def update(self, index, value): if self.is_empty(): raise Exception("List is empty") if index < 0 or index >= self.length: raise Exception("Index out of range") self.data[index] = value ``` 在初始化时,我们需要指定线性表的最大长度,然后创建一个长度为最大长度的数组来存储数据。长度和数据都初始为None或0。在插入、除、获取和更新等操作中,我们需要判断线性表是否为空或已满,以及索引是否越界。如果满足条件,我们就可以对数组进行相应的操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值