B站 搜索帅小柏,关注一下。
一, 线性表
1,顺序表
1.1,顺序存储表示
l o c ( a i ) = l o c ( a 1 ) + ( i − 1 ) ∗ l loc(ai)=loc(a1)+(i-1)*l loc(ai)=loc(a1)+(i−1)∗l
顺序存储结构是一种随机存取的存储结构。
1.2,顺序表的初始化
typedef struct
{
int *elem;//存储空间的基地址
int length;
}sqlist;
int init(sqlist &l)
{
l.elem=new int[100];
if(!l.elem)exit(1);
l.length=0;
return 0;
}
1.3,顺序表的取值
int getelem(sqlist &l,int i,int &e)//i是位置 e是要返回的媒介
{
if(i<1||i>l.length) return error;
e=l.elem[i-1];//因为下标0开始 所以i-1
return ok;
}
1,4 顺序表的查找
int find(sqlist &l int e)//e:要寻找的值
{
for(int i=0;i<l.length;i++)
{
if(l.elem[i]==e) return i+1;//查找成功,返回i+1
}
return 0;//查找失败
}
1.5 顺序表的插入
从下标为i-1 整体往后移,再把插入的e 放到下标为i-1的位置 ,长度再+1。
int inserts(sqlist &l,int i,int e)
{
if(i<1||i>l.length+1) return error;//i不合法
if(l.length==maxsize) return error;//空间满
for(int j=l.length-1;j>=i-1;i--)
{
l.elem[j+1]=l.elem[j];
}
l.elem[i-1]=e;
l.length++;
return ok;
}
1.6 顺序表的删除
int erases(sqlist &l,int i)
{
if(i<1||i>l.length+1) return error;//i不合法
for(int j=i;j<=l.length-1;j++)
{
l.elem[j-1]=l.elem[j];
}
--l.length;
return ok;
}
1.7 顺序表的元素逆置
void reverse(Sqlist &L) {
int i, j, temp;
for (i = 0, j = L.length - 1; i < j; ++i, --j) {
// 头尾两两交换
temp = L.data[i];
L.data[i] = L.data[j];
L.data[j] = temp;
}
}
1.8 删除下标为i~j的数据元素
void deleteRange(Sqlist &L, int i, int j) {
assert(0 <= i && 0 <= j && i < L.length && j < L.length);
// 用j+1后面的元素去覆盖往前数第j-i+1个元素
int delta = j - i + 1;
for (int k = j+1; k < L.length; ++k) {
L.data[k-delta] = L.data[k];
}
L.length -= delta;
}
1.9 Partition操作
void partition(Sqlist &L) {
assert(L.length != 0);
int p = L.data[0];
int i = 0, j = L.length-1;
while (i < j) {
while (i < j && L.data[j] > p) --j;
if (i < j) {
L.data[i] = L.data[j];
++i;
}
while (i < j && L.data[i] < p) ++i;
if (i < j) {
L.data[j] = L.data[i];
--j;
}
}
L.data[i] = p;
}
2 单链表
2.1单链表的初始化
#include <iostream>
#include <stdlib.h>
#define MAXSIZE 1000
#define OK 1
#define ERROR 0
#define Status int
#define OVERFLOW -2
#define ElemType string
using namespace std;
typedef struct LNode {
ElemType data; //结点的数据域
struct LNode *next; //结点的指针域
} LNode, *LinkList; //LinkList为指向结构体LNode的指针类型
Status InitList(LinkList &L)
{
L=new LNode;
L->next=NULL;
return 0;
}
2.2单链表的取值
Status GetElem(LinkList L, int i, ElemType &e)
{
LNode *p;
int j=1;//计算器j
p=L->next;//p指向首元结点
while(p&&(j<i))//直至p为空或者 p指向第i个元素
{
p=p->next;j++;
}
if(!p||(j>i))return -1;
e=p->data;//取出第i个元素
return 0;
}
2.3单链表的按值查找
LinkList LocateElem(LinkList L, ElemType &e)
{
LNode *p;
p=L->next;
while(p&&(p->data!=e))p=p->next;
return p;//返回地址p
}
2.4单链表的插入
Status ListInsert(LinkList &L, int i, ElemType e)
{
LNode *p;
LNode *s;//s为要插入的元素
p=L;
int j=1;
while(p&&(j<i))//让p指向第i-1个元素 且防止p为空
{
p=p->next;j++;
}
s = new LNode;
s->data=e;
//-----------------
s-> next=p->next;
p->next=s;
//------------------
return 0;
}
2.5单链表的删除
Status ListDelete(LinkList &L, int i)
{
LNode *p,*q;
p=L;
int j=1;
while((p->next)&&(j<i))//让p指向第i-1个元素 ,(p->next)含义是 最坏情况 p->next=Null指向最后一个元素。删除不扑空。
{
p=p->next;j++;
}
q=new LNode;//q用来接力 使p指向下下一个元素
//---------------
q=p->next;
p->next=q->next;
//----------------
delete q;
return 0;
}
2.6 单链表的创建
2.6.1 头插法
void CreateList_H(LinkList &L, int n)
{
LNode *p;
L=new LNode;
L->next=NULL;
for(int i=0;i<n;i++)
{
p=new LNode;
cin>>p->data;
//-------------
p->next=L->next;
L->next=p;
//--------------
}
}
2.6.1 尾插法
void createlistR(LNode *&list, int n) {
LNode *s, *r; // s用来指向新申请的节点,r **始终** 指向list的终端节点
int i;
list =new LNode;
list->next = NULL;
r = list;
for (int i = 0; i < n; i++) {
s = new LNode;
cin>>s->data ;
s->next=NULL;
//-----------------
r->next = s; // 让当前的终端节点指向新来的节点
r = r->next; // 更新r,让r指向新的终端节点
}
//r->next = NULL;
2.7 合并递增单链表
void mergeR(LNode *A, LNode *B, LNode *&C) {
// 由于不能改变了A, B自己的内容,所以得设定p, q来进行操作
LNode *p = A->next;
LNode *q = B->next;
LNode *r; // r始终指向C的终端节点
C = A; // 将A的头结点用来做C的头结点
C->next = NULL;
//free(B);
r = C; // 初试的时候C也是终端节点
while (p != NULL && q != NULL) {
if (p->data <= q->data) {
r->next = p; // 让当前的终端节点指向新的终端节点
p = p->next; // p自然要往后挪一步
r = r->next; // 更新r的指向,让r指向新的终端节点
} else {
r->next = q;
q = q->next;
r = r->next;
}
}
// p还有剩余
if (p != NULL) {
r->next = p;
}
// q还有剩余
if (q != NULL) {
r->next = q;
}
}
2.8 合并递减单链表
void mergeF(LNode *A, LNode *B, LNode *&C) {
LNode *p = A->next;
LNode *q = B->next;
LNode *s;
C = A;
C->next = NULL;
free(B);
while (p != NULL && q != NULL) {
if (p->data <= q->data) {
// 这里就体现出s的作用了
// 如果没有s,
// 则直接p->next = C->next,
// 那么改变了p的指向,p无法再往后挪了
s = p;
p = p->next;
s->next = C->next;
C->next = s;
} else {
s = q;
q = q->next;
q->next = C->next;
C->next = s;
}
}
// 由于头插,所以这里必须循环将每个剩余元素放到链表C的前面去
while (p != NULL) {
s = p;
p = p->next;
s->next = C->next;
C->next = s;
}
while (q != NULL) {
s = q;
q = q->next;
s->next = C->next;
C->next = s;
}
}
** 线性表的总结** (重点)
地址公式:
a i = a 1 + ( i − 1 ) ∗ l a_i=a_1+(i-1)*l ai=a1+(i−1)∗l
顺序表の 平均移动次数:
插入:
E i n s e r t = n 2 E_insert=\frac{n}{2} Einsert=2n
删除:
E d e l e t e = n − 1 2 E_delete=\frac{n-1}{2} Edelete=2n−1
顺序表の 移动元素的个数:
插入:
n − i + 1 n-i+1 n−i+1
删除:
n − i n-i n−i
二, 栈与队列
1,顺序栈
typedef struct SqStack{
int data[maxSize];
int top;
} SqStack;
void initStack(SqStack &st) {
st.top = -1;
}
int isEmpty(SqStack st) {
return st.top == -1;
}
int push(SqStack &st, int x) {
if (st.top == maxSize) return 0;
st.data[++st.top] = x;
return 1;
}
int pop(SqStack &st, int &x) {
if (st.top == -1) return 0;
x = st.data[st.top--];
return 1;
}
//------------考试中顺序栈用法的简洁写法------------------
int stack[maxSize]; int top = -1; // 这两句话连定义带初始化都有了
stack[++top] = x; // 一句话实现进栈 -
x = stack[top--]; // 一句话实现出栈 -
//----------------------------------------------------
2,链栈
头插头删
注:要不要头结点都可以。
typedef struct LNode{
int data;
struct LNode *next;
} LNode;
void initStack(LNode *&lst) {
lst = (LNode*)malloc(sizeof(LNode));
lst->next = NULL; // 还是老规矩:申请新的节点后一定要为其指针域设置为空
}
int isEmpty(LNode *lst) {
return lst->next == NULL;
}
void push(LNode *lst, int x) {
// 步骤一:申请新的节点,存放x的值
// 步骤二:头插法将新的节点插入链栈中
LNode *p = (LNode*)malloc(sizeof(LNode));
p->data = x;
//----------------
p->next = NULL;
p->next = lst->next;
lst->next = p;
}
int pop(LNode *lst, int &x) {
// 步骤一:判空
// 步骤二:删除节点
if (lst->next == NULL) return 0;
x = lst->data;
LNode *p;
//------------------------
p = lst->next;
lst->next = lst->next->next;
free(p);
return 1;
}
int gettop(lnode *s){
if(s!=null)
return s->data;
}
3,顺序队列
typedef struct {
int data[maxSize];
int front; // 队首指针
int rear; // 队尾指针
}SqQueue;
void initQueue(SqQueue &qu) {
qu.front = qu.rear = 0; // 队首和队尾指针重合,并且指向0
}
void initQueue(SqQueue &qu) {
qu.front = qu.rear = 0; // 队首和队尾指针重合,并且指向0
}
int inQueue(SqQueue &qu, int x) {
if ((qu.rear+1)%maxSize == qu.front) return 0; // 队满则不能入队
qu.rear = (qu.rear+1)%maxSize; // 若未满,则先移动指针
qu.data[qu.rear] = x; // 再放入元素
return 1;
}
int deQueue(SqQueue &qu, int &x) {
if (qu.front == qu.rear) return 0; // 若队空,则不能删除
qu.front = (qu.front+1)%maxSize; // 若队不空,则先移动指针
x = qu.data[qu.front]; // 再取出元素
return 1;
}
3,链队
typedef struct QNode {
int data; // 数据域
struct QNode *next; // 指针域
}QNode;
typedef struct {
QNode *front; // 队头指针
QNode *rear; // 队尾指针
}LiQueue;
void init_Queue(LiQueue *&lqu) {
lqu = (LiQueue*)malloc(sizeof(LiQueue));
lqu->front = lqu->rear = nullptr;
}
int isQueue_Empty(LiQueue *lqu) {
return (lqu->rear == nullptr || lqu->front == nullptr); // 注意有两个
}
void enQueue(LiQueue *lqu, int x) {
QNode *p;
p = (QNode*)malloc(sizeof(QNode));
p->data = x;
p->next = nullptr;
if (lqu->rear == nullptr) {
// 若队列为空,则新结点是队首结点,也是队尾结点
lqu->front = lqu->rear = p;
} else {
lqu->rear->next = p; // 将新结点链接到队尾,rear指向它
lqu->rear = p;
}
}
int deQueue(LiQueue *lqu, int &x) {
QNode *p;
if (lqu->rear == nullptr) {
// 队空不能出队
return 0;
} else {
p = lqu->front;
}
if (lqu->front == lqu->rear) {
// 队列中只有一个结点时的出队操作需要特殊处理
lqu->front = lqu->rear = nullptr;
} else {
lqu->front = lqu->front->next;
}
x = p->data;
free(p);
return 1;
}