目录
顺序表
顺序表的定义和初始化
顺序表的基本操作
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。为了操作上的方便,在单链表第一个结点之前附加一个结点,称为头结点。头结点的数据域可以不设任何信息,也可以记录表长等信息。头结点的指针域指向线性表的第一个元素结点
头结点和头指针的区分:不管带不带头结点,头指针都始终指向链表的第一个结点,而头结点是带头结点的链表中的第一个结点,结点内通常不存储信息文章来源:https://www.toymoban.com/news/detail-715257.html
单链表的定义
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;
}
按值查找文章来源地址https://www.toymoban.com/news/detail-715257.html
//按值查找,找到数据域等于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;
}
到了这里,关于线性表的基本操作(初始化、创建、增、删、查)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!