数据结构
一、线性表
1.1、顺序表
-
#include <cstdio> #include <cstdlib> /* * 线性表实现 */ #define MAXSIZE 100 //定义顺序表能达到的最大长度 typedef int Status; typedef int ElemType; #define OK 0; #define ERROR 1; /** * 定义一个线性表 */ typedef struct { //存储空间的基地址 ElemType *elem; //当前长度 int length; //顺序表的结构类型为sqList }SqList; /** * 初始化线性表 * @param L * @return */ Status InitList(SqList &L){ //给顺序表分配了一个大小为MAXSIZE大小的数组空间 L.elem = new ElemType[MAXSIZE]; if (!L.elem){ //存储分配失败时退出 exit(0); } //初始化线性表长度为0 L.length = 0; return OK; } /** * 取值操作 * @param L 线性表 * @param i 取值的位置 * @param e 取出的值 * @return */ Status GetElem(SqList L,int i,ElemType &e){ if (i < 1 || i > L.length){ //判断 i 的值是否合法 return ERROR; } //将取来的值赋值给 e e = L.elem[i-1]; return OK; } /** * 查找指定值的元素 * @param L 顺序表 * @param e 需要查找的值 * @return */ int LocateEle(SqList L,ElemType e){ //在顺序表L中查找值为e的数据元素,并返回去序号 for (int i = 0;i<L.length;i++){ //查找成功返回 i +1 ,因为数组的小标是从 0 开始的 if (L.elem[i] == e){ return i + 1; } } return 0; } /** * 插入数据 * @param L 顺序表 * @param i 插入的位置 * @param e 插入的数据 * @return */ Status ListInsert(SqList &L,int i ,ElemType e){ //在顺序表L中第i个位置插入新的元素e,i的值的合法范围是 1<=i<=L.length + 1 if (i < 1 || (i > L.length + 1)){ //i值不合法 return ERROR; } //从后往前替换,遍历到i-1(数组下标是从零开始,而位置是从1开始)这个位置停止,空出要插入的位置 for (int j = L.length-1;j>=i-1;j--){ L.elem[j+1] = L.elem[j]; } //插入数据 L.elem[i-1] = e; //长度加一 ++L.length; return OK; } /** * 删除数据 * @param L 顺序表 * @param i 删除的位置 * @return */ int ListDelete(SqList &L,int i){ if (i < 1 || (i > L.length+1)){ return ERROR; } for (int j = i;j<L.length;j++){ L.elem[j-1] = L.elem[j]; } --L.length; return OK; } int main(){ SqList L; InitList(L); ElemType num1 = 1; ElemType num2 = 2; ElemType num3 = 3; ListInsert(L,1,num1); ListInsert(L,2,num2); ListInsert(L,3,num3); for (int i = 0;i<L.length;i++){ printf("%d ",L.elem[i]); } printf("\n"); ListDelete(L,2); for (int i = 0;i<L.length;i++){ printf("%d ",L.elem[i]); } return 0; }
1.2、链表
1.2.1、链表的插入
-
实例代码
-
/** * 插入值 * @param L 要插入的链表,传入的是地址 * @param i 插入的位置 * @param e 插入的值 * @return */ Status ListInsert(LinkList &L,int i,ElemType e){ if (i < 1){ return ERROR; } //初始化p指向首结点 LinkList p = L; int j = 0; //当结点p为null 或者 j = i-1,也就是找到插入位置的前一个结点 while (p && j < i-1){ p = p->next; ++j; } //如果p不存在或者j>i-1退出 if (!p || j > i-1){ return ERROR; } //生成一个新结点 auto s = new LNode; //将插入的值赋值给新结点 s->data = e; //将新阶段的指针指向插入位置的后面这个结点 s->next = p->next; //将插入位置前一个结点指向新结点,完成新结点的插入 p->next = s; return OK; }
-
1.2.2、删除
-
/** * 删除结点 * @param L 传入的是链表的地址 * @param i 指定删除的位置 * @return */ Status ListDelete(LinkList &L,int i){ if (i < 1){ return ERROR; } //初始化p指向首结点 LinkList p = L; int j = 0; //当结点p的next为null,说明已经到了最后一个结点,说明i不合法 或者 j = i-1,也就是找到删除位置的前一个结点 while (p->next && j < i-1){ p = p->next; ++j; } //如果p的下一个结点为null说明遍历到了最后一个结点,表示位置i是不合法的,或者j>i-1退出 if (!p->next || j > i-1){ return ERROR; } //保存删除的结点,以备后续释放内存 LinkList q = p->next; //将删除结点的上一个结点的指针,指向删除结点的下一个节点,也就是跨过删除结点 p->next = q->next; delete q; return OK; }
1.2.3、头插法
-
/** * 头插法插入结点(新插入的结点总是在老结点的前面,也就是新插入的结点总是在头的后一位) * @param L 链表 * @param n 要插入的结点个数 */ void CreateLink_Head(LinkList &L,int n){ //先建立一个带头结点的空链表 L = new LNode; L->next = nullptr; for (int i = 0;i<n;i++){ //生成一个新的结点 auto p = new LNode; //输入元素值,并赋值给新结点 p 的数据域 cin >> p->data; //将新结点 p 插入到头结点的后面 p->next = L->next; L->next = p; } }
1.2.4、尾插法
-
/** * 尾插法插入结点(新插入的结点总是在老结点的后面) * @param L * @param n */ void CreateLink_Last(LinkList &L,int n){ //先建立一个带头结点的空链表 L = new LNode; L->next = nullptr; //建立一个尾指针指向最后一个结点,现在没有首结点,指向头结点 LinkList r = L; for (int i = 0;i<n;i++){ //生成一个新的结点 auto p = new LNode; //赋值 cin >> p->data; //将新结点的next置空 p->next = nullptr; //将最后一个结点的指向,指向新结点 r->next = p; //将尾指针指向最后一个结点 r = p; } }
1.2.5、完整的代码
-
#include <cstdio> #include <iostream> using namespace std; typedef int Status; //好处是可以随时修改单链表中的类型 typedef int ElemType; #define OK 0; #define ERROR 1; typedef struct LNode{ //数据域 ElemType data; //结点的指针域 struct LNode *next; }LNode,*LinkList; //LinkList为指向结构体LNode的指针类型 /** * 链表的初始化 * @param L 链表 * @return */ Status InitList(LinkList &L){ //生成一个节点作为头节点,用头指针L指向头结点 L = new LNode; //给指针域置空 L->next = nullptr; return OK; } /** * 取值操作---根据序号获取值,并返回 * @param L 链表 * @param i 取值的位置 * @param e 取的值 * @return */ Status GetElem(LinkList L,int i,ElemType e){ //初始化,将p指向首元结点 LinkList p = L->next; int j = 1; //当p不存在 或者 j的值大于取值序号i时,退出循环 while (p && j < i){ //p指向下一个结点 p = p->next; //计数器加一 ++j; } //如果p不存在或者j>i时退出 if(!p || j > i){ return ERROR; } e = p->data; return OK; } /** * 通过指定的 值 进行查找,返回结点地址 * @param L 链表 * @param e 想要查找的值 * @return 返回查找到的结点 */ LNode *LocateElem(LinkList L,ElemType e){ //初始化,将p指向首元结点 LinkList p = L->next; //当p不存在 或者 找到结点值等于 e 时循环退出 while(p && p->data !=e){ p = p->next; } return p; } /** * 插入值 * @param L 要插入的链表,传入的是地址 * @param i 插入的位置 * @param e 插入的值 * @return */ Status ListInsert(LinkList &L,int i,ElemType e){ if (i < 1){ return ERROR; } //初始化p指向首结点 LinkList p = L; int j = 0; //当结点p为null 或者 j = i-1,也就是找到插入位置的前一个结点 while (p && j < i-1){ p = p->next; ++j; } //如果p不存在或者j>i-1退出 if (!p || j > i-1){ return ERROR; } //生成一个新结点 auto s = new LNode; //将插入的值赋值给新结点 s->data = e; //将新阶段的指针指向插入位置的后面这个结点 s->next = p->next; //将插入位置前一个结点指向新结点,完成新结点的插入 p->next = s; return OK; } /** * 删除结点 * @param L 传入的是链表的地址 * @param i 指定删除的位置 * @return */ Status ListDelete(LinkList &L,int i){ if (i < 1){ return ERROR; } //初始化p指向首结点 LinkList p = L; int j = 0; //当结点p的next为null,说明已经到了最后一个结点,说明i不合法 或者 j = i-1,也就是找到删除位置的前一个结点 while (p->next && j < i-1){ p = p->next; ++j; } //如果p的下一个结点为null说明遍历到了最后一个结点,表示位置i是不合法的,或者j>i-1退出 if (!p->next || j > i-1){ return ERROR; } //保存删除的结点,以备后续释放内存 LinkList q = p->next; //将删除结点的上一个结点的指针,指向删除结点的下一个节点,也就是跨过删除结点 p->next = q->next; delete q; return OK; } /** * 头插法插入结点(新插入的结点总是在老结点的前面,也就是新插入的结点总是在头的后一位) * @param L 链表 * @param n 要插入的结点个数 */ void CreateLink_Head(LinkList &L,int n){ //先建立一个带头结点的空链表 L = new LNode; L->next = nullptr; for (int i = 0;i<n;i++){ //生成一个新的结点 auto p = new LNode; //输入元素值,并赋值给新结点 p 的数据域 cin >> p->data; //将新结点 p 插入到头结点的后面 p->next = L->next; L->next = p; } } /** * 尾插法插入结点(新插入的结点总是在老结点的后面) * @param L * @param n */ void CreateLink_Last(LinkList &L,int n){ //先建立一个带头结点的空链表 L = new LNode; L->next = nullptr; //建立一个尾指针指向最后一个结点,现在没有首结点,指向头结点 LinkList r = L; for (int i = 0;i<n;i++){ //生成一个新的结点 auto p = new LNode; //赋值 cin >> p->data; //将新结点的next置空 p->next = nullptr; //将最后一个结点的指向,指向新结点 r->next = p; //将尾指针指向最后一个结点 r = p; } } int main(){ LinkList L; InitList(L); CreateLink_Last(L,2); ElemType num3 = 3; ListInsert(L,3,num3); LinkList p = L; ListDelete(L,3); ListDelete(L,5); while (p){ p = p->next; printf("%d ",p->data); } return 0; }