C 链表模板及笔记 原创

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*指针

posted @   俺叫西西弗斯  阅读(0)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示