文章目录
- Intro
- 理解线性表的基本概念(逻辑特性、术语及物理存储)
- 基本概念
- n (n>=0)个数据特性相同的元素构成的有限序列称为 线性表
- 逻辑特性
- 存在 唯一的一个 被称作 "第一个" 的 数据元素
- 存在 唯一的一个 被称作 "最后一个" 的 数据元素
- 除第一个之外,结构中 每个元素 只有一个前驱
- 除最后一个之外,结构中 每个元素 只有一个后驱
- 术语
- 物理存储
- 一片连续的 存储地址 -> 顺序表
- 可非连续的 存储地址 -> 链式
- 单链表
- 双向链表
- 双向循环链表
- 顺序表
- 循环链表
- 一元多项式的表示与相加
- 有序表的合并
- DevLog
Intro
理解线性表的基本概念(逻辑特性、术语及物理存储)
基本概念
n (n>=0)个数据特性相同的元素构成的有限序列称为 线性表
逻辑特性
存在 唯一的一个 被称作 “第一个” 的 数据元素
存在 唯一的一个 被称作 “最后一个” 的 数据元素
除第一个之外,结构中 每个元素 只有一个前驱
除最后一个之外,结构中 每个元素 只有一个后驱
术语
物理存储
一片连续的 存储地址 -> 顺序表
可非连续的 存储地址 -> 链式
单链表
/*
* @Author:
* @data: 2019-12-02 14:49:03
* @Last Modified by:
* @Last Modified time: 2019-12-02 15:54:49
*/
#include <iostream>
#include <cstdio>
using namespace std;
typedef int Status;
typedef int Elem;
typedef struct LNode
{
/* data */
Elem data;
struct LNode *next; //想起 (数据结构是递归的 LNode 结点 由 data next 组成,而next本身是一种指向LNode 的指针 即LNode定义中调用了自身, 所以连表示一种递归的数据结构 这句台词在栈里 你说操蛋不操蛋
} LNode, *LinkList; //理解成 LNode头 *LinkList 除了头以外的? 大概
//初始化
Status InitList(LinkList &L)
{
L = new LNode; //申请一手内存 指向一片空空如也
L->next = NULL;
return 1;
}
//取值
Status GetElemList(LinkList &L, int i, Elem &e) //提一提这个e 很蛋疼 说老实话我不明白为什么要返回它出来看看你丢了啥
{
LNode *p = L->next; //你好 头节点
int j = 1;
while (p && j < i)
{
p = p->next; //常规遍历
++j;
}
if (!p || j > i)
return -1;
e = p->data;
return 1;
}
//插入
Status InsertList(LinkList &L, int i, Elem e)
{
LNode *p = L;
int j = 0;
while (p && j < i - 1)
{
p = p->next;
j++;
}
if (!p || j > i - 1)
return -1;
LNode *s = new LNode;
s->data = e;
s->next = p->next; //指向头节点指向的 看视频比较好理解
p->next = s; //头节点又指向这个新的
return 1;
}
//长度
Status LenList(LinkList &L, Elem &e)
{
LNode *p = L->next;
int j = 0;
while (p)
{
p = p->next;
++j;
}
if (p)
return -1;
e = j; //有一说一 遍历计数
return 1;
}
//删除
Status DelList(LinkList &L, int i)
{
LNode *p = L->next;
int j = 0;
while ((p->next) && (j < i - 1))
{
p = p->next;
++j;
}
if (!p->next || j > i - 1)
return -1;
LNode *q = p->next;
p->next = q->next;
delete q;//其实这里 q才是目标 因为之前循环都只到i-1 P直接指向下下个 删了Q Q太难了
return 1;
}
//排序
Status SortList(LinkList &L)
{
LNode *p = L->next;
LNode *TmpNode;
int tmp = 0;
while (p)
{
TmpNode = p;
while (TmpNode) //有一说一 我正常冒泡不知道为什么挂球了
{
if (p->data > TmpNode->data)
{
tmp = p->data;
p->data = TmpNode->data;
TmpNode->data = tmp;
}
TmpNode = TmpNode->next;
}
p = p->next;
}
return 1;
}
//遍历
Status ShowList(LinkList &L)
{
LNode *p = L->next;
while (p)
{
cout << p->data << " ";
p = p->next; //直接遍历
}
return 1;
}
//头插
Status CreatList_H(LinkList &L, int num)
{
L = new LNode;
L->next = NULL;
for (int i = 0; i < num; i++)
{
LNode *p = new LNode;
cin >> p->data;
p->next = L->next; //上面我写了
L->next = p;
}
return 1;
}
//尾插
Status CreatList_L(LinkList &L, int num)
{
L = new LNode;
L->next = NULL;
LNode *r = L;
for (int i = 0; i < num; i++)
{
LNode *p = new LNode;
cin >> p->data;
p->next = NULL;
r->next = p;
r = p;//重点就是这个啊 r指向了P 一直走下去
}
return 1;
}
int main()
{
LinkList L;
//1
InitList(L);
//1
int num;
cin >> num;
//CreatList_H(L, num);
//1
CreatList_L(L, num);
//1
//cout << InsertList(L, 1, 1);
//1
int e;
GetElemList(L, 1, e);
cout << "Elem 1 " << e << " ";
//1
int len;
LenList(L, len);
cout << "len:" << len << " ";
//1
int len2;
//DelList(L, 1);
//LenList(L, len2);
//cout << "AfterDellen " << len2<<" ";
//1
SortList(L);
//cout<<L->next->data;
//1
ShowList(L);
}
双向链表
#include <iostream>
#include <cstdio>
using namespace std;
typedef int Elem;
typedef int Status;
typedef struct DulList //我猜是 doubole list...
{
/* data */
Elem data;
struct DulList *prior;
struct DulList *next; // 前 后 指针
} DulList, *DulLinkList;
Status InitDulList(DulLinkList &L)
{
L = new DulList;
L->next = NULL;
L->prior = NULL;
return 1;
}
Status CreatDulList_H(DulLinkList &L, int num)
{
L = new DulList;
L->next = NULL;
for (int i = 1; i <= num; i++)
{
DulList *p = new DulList;
cin >> p->data;
p->next = L->next;
if (L->next) L->next->prior = p;
L->next = p;
p->prior = L;
}
return 1;
}
DulList* GetElemDulList(DulLinkList &L, int i) //这个真就 DulList* ...
{
DulList *p = L;
int j = 0;
while (p && j < i)
{
p = p->next;
++j;
}
if (i<1 || j>i)
;//这个不该这么写 其实
return p;
}
Status InsertDulList(DulLinkList &L, int i, Elem e)
{
DulList *p = L;
if (!(p = GetElemDulList(L, i))) //P的位置其实被改了 不会出现 插在头的情况
return -1;
DulList *s = new DulList;
s->data = e;
s->prior = p->prior;
p->prior->next = s;
s->next = p;
p->prior = s;
return 1;
}
Status DelDulList(DulLinkList &L, int i) //Delete
{
DulList *p = L->next;
if (!(p = GetElemDulList(L, i)))
return -1;
DulList *s = new DulList;
p->prior->next = p->next;
p->next->prior = p->prior; //前后跳着指 中间就空一格了
return 1;
}
Status ShowDulList(DulLinkList &L) {
DulList *p = L->next;
while (p)
{
cout << p->data<<" ";
p = p->next;
}
return 1;
}
int main()
{
DulLinkList L;
//1
InitDulList(L);
//1
CreatDulList_H(L, 3);
//1
InsertDulList(L, 2, 1);
//1
ShowDulList(L);
//1
DelDulList(L, 2);
//1
ShowDulList(L);
}
双向循环链表
#include <iostream>
#include <cstdio>
using namespace std;
typedef int Elem;
typedef int Status;
typedef struct DulList
{
/* data */
Elem data;
struct DulList *prior;
struct DulList *next;
} DulList, *DulLinkList;
Status InitDulList(DulLinkList &L)
{
L = new DulList;
L->next = NULL;
L->prior = NULL;
return 1;
}
Status CreatDulList_H(DulLinkList &L, int num)
{
L = new DulList;
L->next = NULL;
for (int i = 1; i <= num; i++)
{
DulList *p = new DulList;
cin >> p->data;
p->next = L->next;
if (L->next)
L->next->prior = p;
L->next = p;
p->prior = L;
}
return 1;
}
Status ShowDulList(DulLinkList &L)
{
DulList *q = L->next;
while (q->next)
q = q->next;
q->next = L->next;//怎么双向没写 我试了一下 把尾巴指向头 就循环了...
DulList *p = L->next;
while (p)
{
cout << p->data << " ";
p = p->next;
}
return 1;
}
int main()
{
DulLinkList L;
//1
InitDulList(L);
//1
CreatDulList_H(L, 3);
//1
ShowDulList(L);
}
顺序表
/*
* @Author:
* @data: 2019-12-02 13:46:20
* @Last Modified by:
* @Last Modified time: 2019-12-03 20:18:30
*/
#include <iostream>
#include <cstdio>
using namespace std;
#define MAXSIZE 100
typedef int Status;
typedef int Elem;
typedef struct
{
/* data */
Elem *data; //这里其实是整了个数组
int len;
} SqList;//Sq 是 Squence的意思
//初始化
Status InitList(SqList &L)
{
L.data = new Elem[MAXSIZE]; //申请 内存
L.len = 0;
if (L.data)
return -1;
return 1;
}
//取值
Status GetList(SqList &L, int i, Elem &e)
{
if (i < 1 || i > L.len)
return -1;
e = L.data[i - 1];
return e;
}
//按值查找
Status Locatedata(SqList L, Elem e) //你可能要问了 为什么 这里没有&? 因为我查找不需要改它本身...
{
for (int i = 0; i < L.len; i++)
if (L.data[i] == e)
return i + 1;
return 1;
}
//插入
Status InsertList(SqList &L, int i, Elem e)
{
if (i < 1 || i > L.len + 1)
return -1;
if (L.len == MAXSIZE)
return -1;
for (int j = L.len; j >= i - 1; j--)
L.data[j + 1] = L.data[j]; //从后往前 覆盖
L.data[i - 1] = e; //猜猜为什么 是i-1? 因为 赋值那里 是从i=0开始的..
++L.len;
return 1;
}
//删除
Status DelList(SqList &L, int i)
{
if (i < 1 || i > L.len)
return -1;
for (int j = i; j < L.len - 1; j++)
L.data[j - 1] = L.data[j]; //依旧是覆盖 减总长
--L.len;
return 1;
}
//清空
Status DelAlList(SqList &L) //随便写的 应该成?...
{
L.data = NULL;
L.len = 0;
return 1;
}
int main()
{
SqList List;
//1
InitList(List);
int num;
cin >> num;
for (int i = 1; i <= num; i++)
{
Elem OBJ;
cin >> OBJ;
//1
InsertList(List, i, OBJ);
}
for (int i = 0; i < List.len; i++)
cout << List.data[i];
//1
DelAlList(List);
//Locatedata(List, 1);
///DelList(List, 1);
for (int i = 0; i < List.len; i++)
cout << List.data[i];
}
循环链表
/*
* @Author:
* @data: 2019-12-03 19:47:29
* @Last Modified by:
* @Last Modified time: 2019-12-03 20:00:06
*/
#include <iostream>
#include <cstdio>
using namespace std;
typedef int Status;
typedef int Elem;
typedef struct LNode
{
/* data */
Elem data;
struct LNode *next;
} LNode, *LinkList;
//初始化
Status InitList(LinkList &L)
{
L = new LNode;
L->next = NULL;
return 1;
}
//遍历
Status ShowList(LinkList &L)
{
//循环链表 特征!
LNode *q = L->next;
while(q->next)
{
q = q->next;
}
q->next = L->next;
LNode *p = L->next;
while (p)
{
cout << p->data << " ";
p = p->next;
}
return 1;
}
//创建
Status CreatList_H(LinkList &L, int num)
{
L = new LNode;
L->next = NULL;
for (int i = 0; i < num; i++)
{
LNode *p = new LNode;
cin >> p->data;
p->next = L->next;
L->next = p;
}
return 1;
}
int main()
{
LinkList L;
int num;
cin >> num;
CreatList_H(L, num);
//1
ShowList(L);
}
一元多项式的表示与相加
/*
* @Author:
* @Date: 2019-12-03 20:48:51
* @Last Modified by:
* @Last Modified time: 2019-12-03 21:05:06
*/
#include <iostream>
#include <cstdio>
using namespace std;
typedef int Status;
typedef int Elem;
typedef struct PNode
{
float coef; //系数
int expn; //指数
struct PNode *next;
} PNode, *Polynomial;
Status CreatPolyn(Polynomial &P, int n)
{
P = new PNode;
P->next = NULL;
for (int i = 1; i <= n; ++i)
{
PNode *s = new PNode;
cin >> s->coef >> s->expn;
PNode *pre = P;
PNode *q = P->next;
while (q&&q->expn < s->expn) //尾插 看指数大小然后就往后面走
{
pre = q;
q = q->next;
}
s->next = q;
pre->next = s;//找到位子 插入
}
return 1;
}
Status AddPolyn(Polynomial &Pa, Polynomial &Pb) //合并
{
PNode *p1, *p2, *p3 = Pa;
p1 = Pa->next, p2 = Pb->next;
p3 = Pa;
while (p1&&p2)
{
int sum = 0;
PNode *r;
if (p1->expn == p2->expn) //如果指数一样大 P1增大 p3负责在路上链接
{
sum = p1->coef + p2->coef;
if (sum)
{
p1->coef = sum;
p3->next = p1;
p3 = p1;
p1 = p1->next;
p2 = p2->next;
}
else {// 空的话 就看后面的
r = p1, p1 = p1->next;
r = p2, p2 = p2->next;
}
}
else if (p1->expn < p2->expn)
{
//连接 p1 后移
p3->next = p1;
p3 = p1;
p1 = p1->next;
}
else
{
//连接p2 后移
p3->next = p2;
p3 = p2;
p2 = p2->next;
}
p3->next = p1 ? p1 : p2; //三元操作符 p1还有就连接p1 否则连接p2
delete Pb;
}
return 1;
}
int main()
{
Polynomial P1, p2;
-
//1
CreatPolyn(P1, 1);
CreatPolyn(p2, 1);
//1
AddPolyn(P1, p2);
cout <<P1->next->coef << " " << P1->next->expn << " ";
}
有序表的合并
/*
* @Author:
* @Date: 2019-12-03 20:18:46
* @Last Modified by:
* @Last Modified time: 2019-12-03 20:44:28
*/
#include <iostream>
#include <cstdio>
using namespace std;
#define MAXSIZE 100
typedef int Status;
typedef int Elem;
typedef struct
{
/* data */
Elem *date;
int len;
} SqList;
//初始化
Status InitList(SqList &L)
{
L.date = new Elem[MAXSIZE];
L.len = 0;
if (L.date)
return -1;
return 1;
}
//插入
Status InsertList(SqList &L, int i, Elem e)
{
if (i < 1 || i > L.len + 1)
return -1;
if (L.len == MAXSIZE)
return -1;
for (int j = L.len; j >= i - 1; j--)
L.date[j + 1] = L.date[j];
L.date[i - 1] = e;
++L.len;
return 1;
}
Status MergeList_Sq(SqList LA, SqList LB, SqList &LC)
{
LC.len = LA.len + LB.len;
LC.date = new Elem[LC.len];
Elem *pa, *pb, *pc;
Elem *pa_last, *pb_last;
pc = LC.date, pa = LA.date, pb = LB.date;
pa_last = LA.date + LA.len - 1;
pb_last = LB.date + LB.len - 1;
//逻辑上好理解 LA LB 一起找 小的就塞到LC 如果都其中一个空了 另一个就全塞进去
while (pa <= pa_last && pb <= pb_last)
{
if (*pa <= *pb) *pc++ = *pa++;
else *pc++ = *pb++;
}
while (pa <= pa_last) *pc++ = *pa++;
while (pb <= pb_last) *pc++ = *pb++;
return 1;
}
int main()
{
SqList LA, LB, LC;
InitList(LA);
InitList(LB);
InitList(LC);
int num_A, num_B;
cin >> num_A;
cin >> num_B;
for (int i = 1; i <= num_A; i++)
{
Elem OBJ;
cin >> OBJ;
//1
InsertList(LA, i, OBJ);
}
for (int i = 1; i <= num_B; i++)
{
Elem OBJ_B;
cin >> OBJ_B;
InsertList(LB, i, OBJ_B);
}
//1
MergeList_Sq(LA, LB, LC);
for (int i = 0; i < LC.len; i++)
cout << LC.date[i];
}
DevLog
1
ypedef是类型定义的意思。typedef struct 是为了使用这个结构体方便。
若struct node{ }这样来定义结构体的话。在定义 node 的结构体变量时,需要这样写:struct node n;
若用typedef,可以这样写:`
typedef struct node{}NODE;
` 。在申请变量时就可以这样写:NODE n;其实就相当于 NODE 是node 的别名。区别就在于使用时,是否可以省去struct这个关键字。
2
线性表与链表中多存在的&符号 是为了给外部变量赋值 直接给到外部的地址中!
3
单链表排序部分出错 冒泡出问题
已改为选择排序 成功
4
*LinkList 其实从始至终都是拿来指向自己的
在这里修改是直接修改的 LIST本身!
*date 可以表示为直接申请一个数组空间
5
双向链表过程中
漏看了 P40 的 if(!(p=GetElem_Dul(L,i))) 内的L
且书中缺少该模块
在 InsertDulList 中 p 出现内存错误
因此发现 返回为 指针属性
依据经验增添 GetElemDulList 如下
DulList* GetElemDulList(DulLinkList &L, int i)
{
DulList *p = L;
int j = 0;
while (p && j < i)
{
p = p->next;
++j;
}
if (i<1 || j>i)
;
return p;
}
p->prior 出现内存错误
依据经验添加 CreatDulList_H 模块
P 持续在 InsertDulList 出现内存错误
推断为 GetElemDulList 中 指针p 移动到了 NULL
更改 while (p && j < i)
无效
排查后发现是 CreatDulList_H 中 prior 的缺失
尴尬 巨尴尬
6
循环链表 看了半天都不知道哪里有
看了看说尾巴指向头
然后我就试了一下 在 遍历 部分 把尾巴指向头 如下:
LNode *q = L->next;
while(q->next)
{
q = q->next;
}
q->next = L->next;
然后就好像成功了… 可以说是极快了…
7
有序表的合并部分
不得不吐槽一下
这他妈?
书上的代码是垃圾吗?
啊 重要是理解算法思维自己做
关键是你写的太繁杂 不如自己写啊喂
MMP 开玩笑吧 我们这个学校的老师教学也跟开玩笑一样
天大的玩笑哦
存在部分问题
8
一元多项式的表示与相加
哇 真实
书上写的这么多
说白了 也就一点点东西
MMP 这部分该老师教的 我教了尼玛个锤子
P48的 P3 不知道应该是指向那里的
后来想了想 *p3 = Pa;
对了
笑死我了
7.2
改完了 我看指针下意识以为是结点
重新写了一遍 半途发现是尼玛的ELEM*指针
赣