写在前面:
这两个数据结构代码量比较大,建议先把代码拷贝到项目里面,然后再回来看接口函数加深理解!!!
💗1、顺序表
💛1.1初识顺序表
顺序表是在计算机内存中以数组的形式保存的线性表,线性表的顺序存储是指用一组地址连续的存储单元依次存储线性表中的各个元素、使得线性表中在逻辑结构上相邻的数据元素存储在相邻的物理存储单元中,即通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系,采用顺序存储结构的线性表通常称为顺序表。
优点:
1、无需为表示表中元素之间的逻辑关系而增加额外的存储空间
2、可以快速地存取表中任一位置的元素,即可以实现随机读取
缺点:
1、插入删除操作需要移动大量元素
2、当线性表长度变化较大时,难以确定存储空间的容量,造成存储空间的碎片
💛 1.2顺序表的实现
我们以动态顺序表为例子,来从头创建一个顺序表
💚1.2.1接口函数的实现
💙初始化
void SeqListInit(SL* ps)
{
ps->a = NULL;
ps->capacity = 0;
ps->size = 0;
//memset(ps->a, 0, sizeof(SQDataType) * MAX_SIZE);
}
💙检查顺序表空间是否已满,满了扩容
void SeqListCheckCapacity(SL* ps)
{
//已经满了,需要动态开辟内存
if (ps->size == ps->capacity)
{
//空间为0则开辟四个,空间满了则开辟为原来的两倍
int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
//之所以用了中间变量tmp接收realloc开辟的值,是由于realloc的特殊性,开辟失败会返回NULL,原来已有内存会被释放
SQDataType* tmp = realloc(ps->a, newcapacity * 2 * sizeof(SQDataType));
//开辟失败
if (tmp == NULL)
{
printf("realloc fail\n");
exit(-1);
}
//确定realloc成功开辟内存后在将开辟的内存赋给ps->a
else
{
ps->a = tmp;
ps->capacity = newcapacity;
}
}
}
💙尾插
很简单直接在数组最后一个位置插入即可
void SeqListPushBack(SL* ps, SQDataType x)
{
//检查空间是否已满,满了扩容
SeqListCheckCapacity(ps);
ps->a[ps->size] = x;
//插入一个数据后,数组大小size增大
ps->size++;
}
💙头插
根据图示,我们将数组里的元素从后往前依次往后挪一个位置,然后在头,也就是a[0]插入即可
void SeqListPushFront(SL* ps, SQDataType x)
{
SeqListCheckCapacity(ps);
int end = ps->size - 1;
while (end >= 0)
{
ps->a[end + 1] = ps->a[end];
--end;
}
ps->a[0] = x;
ps->size++;
}
💙尾删
很多同学也许会把最后一个位置的数据置为0(就像我下面注释掉的那样)。但如果0为有效数据或者数组里面存储的数据是double,float类型的就说不通了,所以这样做是不对的。我们只用将数组大小size减小一个,再进行后续操作的时候只要把原数据覆盖掉就行了。
void SeqListPopBack(SL* ps)
{
//断言如果size=0终止程序
assert(ps->size > 0);
//ps->a[ps->size - 1] = 0;
ps->size--;
}
💙头删
分析图示,我们只需要将顺序表中从start位置开始的数据从前往后依次往前挪一个位置
void SeqListPopFront(SL* ps)
{
//断言如果size=0终止程序
assert(ps->size > 0);
int start = 1;
while (start < ps->size)
{
ps->a[start - 1] = ps->a[start];
++start;
}
ps->size--;
}
💙插入
分析图示,插入分为两步
1、将pos到end位置上的数据从后往前依次往后挪一个位置
2、在pos位置插入数据x
void SeqListInsert(SL* ps, int pos, SQDataType x)
{
//断言如果插入的位置比size还大就终止程序
assert(pos < ps->size);
SeqListCheckCapacity(ps);
int end = ps->size - 1;
while (end >= pos)
{
ps->a[end + 1] = ps->a[end];
--end;
}
ps->a[pos] = x;
ps->size++;
}
💙删除
很简单只需要将start到最后位置的数据从前往后依次往前移
void SeqListErase(SL* ps, int pos)
{
assert(pos < ps->size);
int start = pos + 1;
while (start < ps->size)
{
ps->a[start - 1] = ps->a[start];
++start;
}
ps->size--;
}
💙修改
由于顺序表的特性可以实现随机访问,直接利用索引访问数据修改就可以了
int SeqListModify(SL* ps, int pos, SQDataType x)
{
assert(pos < ps->size);
ps->a[pos] = x;
}
💙查找
遍历整个数组
int SeqListFind(SL* ps, SQDataType x)
{
for (int i = 0; i < ps->size; i++)
{
if (ps->a[i] == x)
{
return i;
}
}
return -1;
}
💙打印
遍历数组然后打印就行了!!!
void SeqListPrint(SL* ps)
{
for (int i = 0; i < ps->size; i++)
{
printf("%d ", ps->a[i]);
}
printf("\n");
}
💚1.2.2 完整代码
SeqList.h
#pragma once
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
#define MAX_SIZE 10
typedef int SQDataType;
typedef struct SeqList
{
SQDataType* a;
int size;//有效数据的个数
int capacity;//容量
}SL;
//增删查改等接口函数
void SeqListInit(SL* ps);//初始化
void SeqListPrint(SL* ps);
void SeqListDestroy(SL* ps);
void SeqListPushBack(SL* ps,SQDataType x);//尾插
void SeqListPushFront(SL* ps, SQDataType x);//头插
void SeqListPopBack(SL* ps);//尾删
void SeqListPopFront(SL* ps);//头删
void SeqListInsert(SL* ps, int pos, SQDataType x);
void SeqListErase(SL* ps, int pos);
int SeqListFind(SL* ps, SQDataType x);
int SeqListModify(SL* ps, int pos, SQDataType x);
SeqList.c
#define _CRT_SECURE_NO_WARNINGS
#include"SeqList.h"
//增删查改等接口函数
void SeqListInit(SL* ps)
{
ps->a = NULL;
ps->capacity = 0;
ps->size = 0;
//memset(ps->a, 0, sizeof(SQDataType) * MAX_SIZE);
}
void SeqListCheckCapacity(SL* ps)
{
if (ps->size == ps->capacity)
{
int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
SQDataType* tmp = realloc(ps->a, newcapacity * 2 * sizeof(SQDataType));
if (tmp == NULL)
{
printf("realloc fail\n");
exit(-1);
}
else
{
ps->a = tmp;
ps->capacity = newcapacity;
}
}
}
void SeqListPushBack(SL* ps, SQDataType x)
{
SeqListCheckCapacity(ps);
ps->a[ps->size] = x;
ps->size++;
}
void SeqListPushFront(SL* ps, SQDataType x)
{
SeqListCheckCapacity(ps);
int end = ps->size - 1;
while (end >= 0)
{
ps->a[end + 1] = ps->a[end];
--end;
}
ps->a[0] = x;
ps->size++;
}
void SeqListPopBack(SL* ps)
{
assert(ps->size > 0);
//ps->a[ps->size - 1] = 0;
ps->size--;
}
void SeqListPopFront(SL* ps)
{
assert(ps->size > 0);
int start = 1;
while (start < ps->size)
{
ps->a[start - 1] = ps->a[start];
++start;
}
ps->size--;
}
void SeqListPrint(SL* ps)
{
for (int i = 0; i < ps->size; i++)
{
printf("%d ", ps->a[i]);
}
printf("\n");
}
void SeqListInsert(SL* ps, int pos, SQDataType x)
{
assert(pos < ps->size);
SeqListCheckCapacity(ps);
int end = ps->size - 1;
while (end >= pos)
{
ps->a[end + 1] = ps->a[end];
--end;
}
ps->a[pos] = x;
ps->size++;
}
void SeqListErase(SL* ps, int pos)
{
assert(pos < ps->size);
int start = pos + 1;
while (start < ps->size)
{
ps->a[start - 1] = ps->a[start];
++start;
}
ps->size--;
}
void SeqListDestroy(SL* ps)
{
free(ps->a);
ps->a = NULL;
ps->capacity = ps->size = 0;
}
int SeqListFind(SL* ps, SQDataType x)
{
for (int i = 0; i < ps->size; i++)
{
if (ps->a[i] == x)
{
return i;
}
}
return -1;
}
int SeqListModify(SL* ps, int pos, SQDataType x)
{
assert(pos < ps->size);
ps->a[pos] = x;
}
Test.c
#define _CRT_SECURE_NO_WARNINGS
#include"SeqList.h"
void TestSeqList1()
{
SL sl;
SeqListInit(&sl);
SeqListPushBack(&sl,1);
SeqListPushBack(&sl, 2);
SeqListPushBack(&sl, 3);
SeqListPushBack(&sl, 4);
SeqListPushBack(&sl, 5);
SeqListPushBack(&sl, 6);
SeqListPrint(&sl);
SeqListInsert(&sl, 1, 20);
SeqListPrint(&sl);
SeqListErase(&sl, 1);
SeqListPrint(&sl);
SeqListDestroy(&sl);
}
enum
{
PushBack = 1,
PushFront,
PopBack,
PopFront,
Insert,
Erase,
Modify,
Find,
Print
};
void menu()
{
printf("************************************\n");
printf("*********** 菜单 ************ \n");
printf("************************************\n");
printf("------------------------------------\n");
printf("****** 1.尾插数据 2.头插数据 ******\n");
printf("****** 3.尾删数据 4.头删数据 ******\n");
printf("****** 5.插入数据 6.删除数据 ******\n");
printf("****** 7.修改数据 8.查找数据 ******\n");
printf("****** 9.打印数据 -1.退出 ******\n");
printf("------------------------------------\n");
printf("************************************\n");
printf("请输入你的操作选项:\n");
}
int main()
{
SL s;
SeqListInit(&s);
int option = 0;
int x = 0;
int pos = 0;
while (option != -1)
{
menu();
scanf("%d", &option);
switch (option)
{
case PushBack:
printf("请输入你要插入的数据,以-1结束\n");
do
{
scanf("%d", &x);
if(x != -1)
{
SeqListPushBack(&s,x);
}
} while (x != -1);
break;
case PushFront:
printf("请输入你要插入的数据,以-1结束\n");
do
{
scanf("%d", &x);
if (x != -1)
{
SeqListPushFront(&s, x);
}
} while (x != -1);
break;
case PopFront:
SeqListPopFront(&s);
break;
case PopBack:
SeqListPopBack(&s);
break;
case Erase:
printf("请输入你要删除的数据,以-1结束\n");
do
{
scanf("%d", &x);
if (x != -1)
{
SeqListErase(&s, x);
}
} while (x != -1);
break;
case Insert:
printf("请输入你要插入数据的位置以及插入值,以-1结束\n");
do
{
scanf("%d %d", &pos,&x);
if (x != -1)
{
SeqListInsert(&s,pos,x);
}
} while (x != -1);
break;
case Modify:
printf("请输入你要修改数据的位置以及修改值,以-1结束\n");
do
{
scanf("%d %d",&pos, &x);
if (x != -1)
{
SeqListModify(&s,pos,x);
}
} while (x != -1);
break;
case Find:
printf("请输入你要查找的数据,以-1结束\n");
do
{
scanf("%d", &x);
if (x != -1)
{
printf("找到了,下标为%d\n",SeqListFind(&s, x));
}
else
{
printf("找不到\n");
}
} while (x != -1);
break;
case Print:
SeqListPrint(&s);
break;
default:
break;
}
}
SeqListDestroy(&s);
TestSeqList1();
return 0;
}
运行结果:
💗2.单链表
💛2.1 初识单链表
单链表是一种链式存取的数据结构,,链表中的数据是以结点来表示的,每个结点的构成:元素 (数据元素的映象) + 指针 (指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。 以“结点的序列”表示的线性表称作线性链表(单链表),单链表是链式存取的结构。
优点:
1、元素的存储单元是任意的,可连续也可不连续。
2、不需要限定长度。
3、删除和插入比较方便
缺点:
①其查找时间复杂度为O(n)。
②存放元素时需要另外开辟一个指针域的空间
💛2.2单链表的实现
以单项不带头的单链表为例
💚2.2.1接口函数的实现
💙创建节点
SLTNode* BuySListNode(SLTDataType x)
{
//为节点开辟一个结构体大小的内存
SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
newnode->data = x;
newnode->next = NULL;
return newnode;
}
💙尾插
根据图示,我们只需要两步
1、找到链表的尾部,定义为tail
2、创建一个新节点(newnode),尾节点链接新节点
//1.使用二级指针,传递指针的地址,从而改变实参的一些属性
void SListPushBack(SLTNode** pphead, SLTDataType x)
{
SLTNode* newnode = BuySListNode(x);
if (*pphead == NULL)
{
*pphead = newnode;
}
else
{
SLTNode* tail = *pphead;
//找尾节点的指针
while (tail->next != NULL)
{
tail = tail->next;
}
//尾节点链接新节点
tail->next = newnode;
}
}
//2.使用c++里面的引用
void SListPushBack(SLTNode*& phead, SLTDataType x)
phead此时为一级指针
{
SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
newnode->data = x;
newnode->next = NULL;
if (phead == NULL)
{
phead = newnode;
}
else
{
SLTNode* tail = *phead;
//找尾节点的指针
while (tail->next != NULL)
{
tail = tail->next;
}
//尾节点链接新节点
tail->next = newnode;
}
}
💙头插
和尾插比起来头插就比较简单了,但这里有一个点需要注意,由于我们改变了形式参数的一些属性,同时希望实参也能跟着改变,所以在这里我们要使用二级指针来接收(形参只是实参的临时拷贝,形参的改变不会改变实参)
void SListPushFront(SLTNode** pphead, SLTDataType x)
{
SLTNode* newnode = BuySListNode(x);
newnode->next = *pphead;
*pphead = newnode;
}
💙尾删
分析图示我们发现实现尾删也不复杂,只需要通过循环找到tail和pre指针后将NULL赋给pre->next就行啦
void SListPopBack(SLTNode** pphead)
{
//1.链表为空
if (*pphead == NULL)
{
return;
}
//2.链表只有一个节点,没进循环,pre为空,释放后pre为野指针
else if ((*pphead)->next == NULL)
{
free(*pphead);
*pphead = NULL;
}
//3.链表有一个以上的节点
else
{
SLTNode* pre = NULL;
SLTNode* tail = *pphead;
//找tail和pre指针
while (tail->next != NULL)
{
pre = tail;
tail = tail->next;
}
free(tail);
pre->next = NULL;
}
}
💙头删
和头插一样我们还是改变了形参的属性但希望实参也能跟着改变
void SListPopFront(SLTNode** pphead)
{
SLTNode* next = (*pphead)->next;//保存plist的下一个节点
free(*pphead);
*pphead = next;
}
💙查找
由于链表是不连续的,我们也只能通过遍历来查找。定义一个cur指针,循环条件为cur!=NULL,循环体内实行操作为cur=cur->next,实现cur对链表的遍历,判断条件为data是否等于x
SLTNode* SListFind(SLTNode* phead, SLTDataType x)
{
SLTNode* cur = phead;
while (cur)
{
if (cur->data == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
💙插入
由于链表物理上是不连续的,所以我们在插入之前需要先找到插入元素的前后节点,即pre和pos然后连接起来。
//在pos的位置插入x
void SListInsert(SLTNode** pphead,SLTNode* pos,SLTDataType x)
{
if (pos == *pphead)//在第一个位置,相当于头插
{
SListPushFront(pphead, x);
}
else
{
SLTNode* newnode = BuySListNode(x);
SLTNode* pre = *pphead;
while (pre->next != pos)
{
pre = pre->next;
}
pre->next = newnode;
newnode->next = pos;
}
}
💙删除
同样通过遍历找到pos位置前一个节点pre,先把pre和pos后一个联系建立起来,然后在free掉pos节点,顺序一定不能换,先free后就找不到后面节点了
//删除pos位置的值
void SListErase(SLTNode** pphead, SLTNode* pos)
{
//头删的时候pre进入while循环后为NULL,需要特殊考虑
if (pos == *pphead)
{
SListPopFront(pphead);
}
else
{
SLTNode* pre = *pphead;
while (pre->next != pos)
{
pre = pre->next;
}
pre->next = pos->next;
free(pos);
}
}
💙计算节点个数
SLTDataType SListLength(SLTNode* phead)
{
int count = 0;
SLTNode* p = phead;
while (p != NULL)
{
count++;
p = p->next;
}
return (count);
}
💚2.2.2全部代码
Slist.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
typedef int SLTDataType;
typedef struct SListNode
{
SLTDataType data;
struct SListNode* next;
}SLTNode;
//不会改变链表的头指针,传一级指针
void SListPrint(SLTNode* phead );
//会改变链表的头指针,传二级指针
void SListPushBack(SLTNode** pphead, SLTDataType x);
void SListPushFront(SLTNode** pphead, SLTDataType x);
void SListPopBack(SLTNode** pphead);
void SListPopFront(SLTNode** pphead);
SLTNode* SListFind(SLTNode* phead, SLTDataType x);
//在pos的位置插入x
void SListInsert(SLTNode** pphead, SLTNode* pos,SLTDataType x);
//删除pos位置的值
void SListErase(SLTNode** pphead);
//数节点个数
SLTDataType SListLength(SLTNode* phead);
Slist.c
#define _CRT_SECURE_NO_WARNINGS
#include"SList.h"
void SListPrint(SLTNode* phead)
{
SLTNode* cur = phead;
while (cur != NULL)
{
printf("%d->", cur->data);
cur = cur->next;
}
printf("NULL\n");
}
SLTNode* BuySListNode(SLTDataType x)
{
SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
newnode->data = x;
newnode->next = NULL;
return newnode;
}
//1.使用二级指针,传递指针的地址,从而改变实参的一些属
void SListPushBack(SLTNode** pphead, SLTDataType x)
{
SLTNode* newnode = BuySListNode(x);
if (*pphead == NULL)
{
*pphead = newnode;
}
else
{
SLTNode* tail = *pphead;
//找尾节点的指针
while (tail->next != NULL)
{
tail = tail->next;
}
//尾节点链接新节点
tail->next = newnode;
}
}
//2.使用c++里面的引用
//void SListPushBack(SLTNode*& phead, SLTDataType x)
//phead此时为一级指针
//{
// SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
// newnode->data = x;
// newnode->next = NULL;
//
// if (phead == NULL)
// {
// phead = newnode;
// }
// else
// {
// SLTNode* tail = *phead;
// //找尾节点的指针
// while (tail->next != NULL)
// {
// tail = tail->next;
// }
//
// //尾节点链接新节点
// tail->next = newnode;
// }
//}
void SListPushFront(SLTNode** pphead, SLTDataType x)
{
SLTNode* newnode = BuySListNode(x);
newnode->next = *pphead;
*pphead = newnode;
}
void SListPopBack(SLTNode** pphead)
{
//1.链表为空
if (*pphead == NULL)
{
return;
}
//2.链表只有一个节点,没进循环,pre为空,释放后pre为野指针
else if ((*pphead)->next == NULL)
{
free(*pphead);
*pphead = NULL;
}
//3.链表有一个以上的节点
else
{
SLTNode* pre = NULL;
SLTNode* tail = *pphead;
while (tail->next != NULL)
{
pre = tail;
tail = tail->next;
}
free(tail);
pre->next = NULL;
}
}
void SListPopFront(SLTNode** pphead)
{
SLTNode* next = (*pphead)->next;//保存plist的下一个节点
free(*pphead);
*pphead = next;
}
SLTNode* SListFind(SLTNode* phead, SLTDataType x)
{
SLTNode* cur = phead;
while (cur)
{
if (cur->data == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
void SListInsert(SLTNode** pphead,SLTNode* pos,SLTDataType x)
{
if (pos == *pphead)//在第一个位置,相当于头插
{
SListPushFront(pphead, x);
}
else
{
SLTNode* newnode = BuySListNode(x);
SLTNode* pre = *pphead;
while (pre->next != pos)
{
pre = pre->next;
}
pre->next = newnode;
newnode->next = pos;
}
}
void SListErase(SLTNode** pphead, SLTNode* pos)
{
//头删的时候pre进入while循环后为NULL,需要特殊考虑
if (pos == *pphead)
{
SListPopFront(pphead);
}
else
{
SLTNode* pre = *pphead;
while (pre->next != pos)
{
pre = pre->next;
}
pre->next = pos->next;
free(pos);
}
}
SLTDataType SListLength(SLTNode* phead)
{
int count = 0;
SLTNode* p = phead;
while (p != NULL)
{
count++;
p = p->next;
}
return (count);
}
Test.c
#define _CRT_SECURE_NO_WARNINGS
#include"SList.h"
enum
{
PushBack = 1,
PushFront,
PopBack,
PopFront,
Insert,
Erase,
Count,
Find,
Print
};
void menu()
{
printf("************************************\n");
printf("*********** 菜单 ************ \n");
printf("************************************\n");
printf("------------------------------------\n");
printf("****** 1.尾插数据 2.头插数据 ******\n");
printf("****** 3.尾删数据 4.头删数据 ******\n");
printf("****** 5.插入数据 6.删除数据 ******\n");
printf("****** 7.节点个数 8.查找数据 ******\n");
printf("****** 9.打印数据 -1.退出 ******\n");
printf("------------------------------------\n");
printf("************************************\n");
printf("请输入你的操作选项:\n");
}
void TestList1()
{
SLTNode* plist = NULL;
SListPushBack(&plist, 1);
SListPushBack(&plist, 2);
SListPushBack(&plist, 3);
SListPushBack(&plist, 4);
SListPushBack(&plist, 5);
SListPrint(plist);
SListPushFront(&plist, 0);
SListPrint(plist);
SListPopFront(&plist);
SListPopFront(&plist);
SListPopFront(&plist);
SListPrint(plist);
SListPopBack(&plist);
SListPrint(plist);
}
void TestList2()
{
SLTNode* plist = NULL;
SListPushBack(&plist, 1);
SListPushBack(&plist, 2);
SListPushBack(&plist, 3);
SListPushBack(&plist, 4);
SListPushBack(&plist, 5);
SListPrint(plist);
//在3前面插入一个30
SLTNode* pos = SListFind(plist, 3);
if (pos)
{
SListInsert(&plist, pos, 30);
}
SListPrint(plist);
}
void TestList3()
{
SLTNode* plist = NULL;
SListPushBack(&plist, 1);
SListPushBack(&plist, 2);
SListPushBack(&plist, 3);
SListPushBack(&plist, 4);
SListPushBack(&plist, 5);
SListPrint(plist);
printf("%d\n", SListLength(plist));
}
void TestList4()
{
SLTNode* plist = NULL;
SListPushBack(&plist, 1);
SListPushBack(&plist, 2);
SListPushBack(&plist, 3);
SListPushBack(&plist, 4);
SListPushBack(&plist, 5);
SListPrint(plist);
SLTNode* pos = SListFind(plist, 1);
if (pos)
{
SListErase(&plist, pos);
}
SListPrint(plist);
pos = SListFind(plist, 2);
if (pos)
{
SListErase(&plist, pos);
}
SListPrint(plist);
pos = SListFind(plist, 3);
if (pos)
{
SListErase(&plist, pos);
}
SListPrint(plist);
pos = SListFind(plist, 4);
if (pos)
{
SListErase(&plist, pos);
}
SListPrint(plist);
pos = SListFind(plist, 5);
if (pos)
{
SListErase(&plist, pos);
}
SListPrint(plist);
}
int main()
{
SLTNode* plist = NULL;
int option = 0;
int x = 0;
int flag = 0;
int position = 0;
while (option != -1)
{
menu();
scanf("%d", &option);
switch (option)
{
case PushBack:
printf("请输入你要插入的数据,以-1结束\n");
do
{
scanf("%d", &x);
if (x != -1)
{
SListPushBack(&plist, x);
}
} while (x != -1);
break;
case PushFront:
printf("请输入你要插入的数据,以-1结束\n");
do
{
scanf("%d", &x);
if (x != -1)
{
SListPushFront(&plist, x);
}
} while (x != -1);
break;
case PopFront:
SListPopFront(&plist);
break;
case PopBack:
SListPopBack(&plist);
break;
case Erase:
printf("请输入你要删除的数据,以-1结束\n");
do
{
scanf("%d", &x);
if (x != -1)
{
SLTNode* pos = SListFind(plist, x);
SListErase(&plist, pos);
}
} while (x != -1);
break;
case Insert:
printf("请输入你要在哪一个数据的前面插入以及插入值,以-1结束\n");
do
{
scanf("%d %d %d", &position,&x,&flag);
SLTNode* pos = SListFind(plist, position);
if (x != -1)
{
SListInsert(&plist, pos, x);
}
} while (flag != -1);
break;
case Count:
printf("节点个数为%d\n",SListLength(plist));
break;
case Find:
printf("请输入你要查找的数据,以-1结束\n");
do
{
scanf("%d", &x);
if (x != -1)
{
printf("找到了\n");
}
} while (x != -1);
break;
case Print:
SListPrint(plist);
default:
break;
}
}
//TestSList1();
//TestList2();
//TestList4();
return 0;
}
运行结果:
💗3.总结
通过顺序表和单链表的学习我们可以进一步体会到两种数据结构的优缺点,可以说顺序表和链表之间是互补的,他们之间并没有绝对的优劣,在不同的应用场景我们应该具体分析到底采用哪一种数据结构,在不久的几天后我还会推出带哨兵位的单向不循环链表,双头循环链表,栈和队列等板块,希望大佬们能够给予斧正,不吝赐教,希望和大家一起进步!!!