【理解】初识链表

链表(增删改查)

记录

初次理解。。。有些偏差
我的链表https://blog.csdn.net/qq_43763494/article/details/101068960链表理解

代码片.

#include<iostream>
#include<cstdlib>
using namespace std;

//宏定义参数内容 
#define DATA_SIZE 200
#define EXTEND_DATA_SIZE 50
#define NO 0
#define OK 1
#define ERROR -1

//基本数据类型别名 
typedef int Status;
typedef char Excelelem;
typedef int Numelem;

//链表数据结构
typedef struct Node		///三条斜杠的为我个人的理解 ///类型定义 Node结构体 起别名为Liststruct 
{
	Excelelem book;			///char类型变量book 链表里存的值(们) 
	struct Node *next;		///结构体指针 Node (就是指向结构体的指针?)
}Liststruct;

//链表表头信息
typedef struct
{
	Excelelem book[1024];		///char类型数组? 
	Liststruct *next;		///这个和Liststruct *newNode 的区别是? 
	Numelem Length;			///int类型变量Length 
}ListHead;				///直接命名结构体ListHead 

//初始化链表
Liststruct * init(int *i)		///初始链表 
{
	Liststruct *Head,*p,*q;		///Liststruct类型头指针,前一结点指针q,后一结点指针p 
	Excelelem ch;			///char类型变量ch 
	Head=q=NULL;			///头指针等于前指针等于空值 
	cout << "请输入顺序表Head的内容:" << endl;
	while((ch=getchar())!='\n'){		///每次while循环接收一个字符,直到换行符(回车)为止 
		p=(Liststruct *)malloc(sizeof(Liststruct));		///分配内存--百度 
		p->book=ch;			///将接收的值赋值给该结点的book 
		if(!(*i)){			///这个(*i)还没搞懂... 
			Head=q=p;
			(*i)++;
		}
		else{
			q->next=p;		///前指针q的next指向p 
			q=p;			///后指针p变为前指针q 
			(*i)++;
		}
	}//注意*q++和(*q)++有区别!
	if(q){
		q->next=NULL;		///初始化链表后将q的next指向NULL(空) (应该是备用) 
	}
	return Head;			///返回头指针的地址
}

ListHead * Headinit()		///头结点 
{
	ListHead *Head;			///声明一个ListHead类型的指针 
	Head=(ListHead *)malloc(sizeof(ListHead));		///分配内存 
	Head->Length=0;			///将表头的Length赋值为0 
	Head->next=init(&Head->Length);		///头结点的next指向初始化链表函数 参数为(Head->Length)的地址 
	return Head;			///返回头指针的地址
}

//打印表中数据内容
void DATA_cout(ListHead *Head)		///定义void类型函数 参数是ListHead类型的指针*Head; 
{
	Liststruct *p=Head->next;		///定义Liststruct类型的结构体指针,并指向Head->next;此时p相当于Head; 
	while(p!=NULL){			///当p->next不为空(也就是不是最后一个结点)时,循环 
		cout << p->book;			///输出对应的结点中的值
		p=p->next;				///将p所指向的结点地址赋值给p(p变为下一个结点)
	}
	cout << endl;				///换行 
	return ;			///这个return可以不返回任何值的么? (void的不需要返回值,这句话应该可以不写)
}

//打印表中local位置元素内容
void Local(ListHead* Head,int local)	///定义void类型函数 参数是结构体指针Head和int类型变量local 
{
	if(Head->Length<local || local<1){			///如果链表的长度小于所输入的位置(即变量local的值)
		cout << "警告!不存在" << local << "位置的元素!" << endl;		///或者local的值小于1,输出警告 
		return ; 
	}
	Liststruct *p=Head->next;		///定义Liststruct类型的结构体指针,并指向Head->next;
	int i=1;					///定义i,赋初值1 
	while(p && i++!=local){			///当p不为空(NULL)且没有找到local位置(i与local不相等)时,循环 
		p=p->next;				///将p所指向的结点地址赋值给p
	}
	cout << p->book << endl;		///输出p此时所在结点的内容(book值) 
	return ;
}

//找到表中出现字符ch的位置 
void DATA_find(ListHead* Head,char ch)		///定义void类型函数 参数是结构体指针Head和char类型变量ch
{
	int i=1,flag=0,count=1;			///定义flag判断是否发现匹配元素 
	Liststruct *p=Head->next;		///定义Liststruct类型的结构体指针,并指向Head->next;
	while(p){					///当p存在时,就是在链表内 
		if(p->book==ch){			///判断当前结点内book是否与要查找的ch匹配 
			flag=1;				///如果匹配,flag值变为1 
			cout << count++ << ".在第" << i << "个位置发现元素" << ch << endl; 
		}
		i++;
		p=p->next;			///将p所指向的结点地址赋值给p
	}
	if(!flag){				///如果flag值为0则说明未在链表内找到对应字符 
		cout << "未找到出现'" << ch << "'元素的位置!" << endl;
	}
	return ;
}

//在第K个元素前插入一个元素
void DATA_Insert(ListHead *Head,int k,Excelelem ch)	///定义void类型函数 参数是结构体指针Head和Excelelem类型变量ch
{													///ch即(要插入的字符),以及int型变量k(即要插入的位置)
	if(k<1 || Head->Length<k){						///首先判断链表中有无这个位置 
		cout << "警告!不存在第" << k << "位置元素" << endl;
		return ; 
	}
	Liststruct *p=Head->next,*q,*t;				///一如既往的定义指针 指针p,前指针t,后指针q 
	int i=1;
	while(p && i++!=k){							///一如既往的寻找k这个位置所对应的结点 
		t=p;								///将上一个结点保留在t 
		p=p->next;							///一如既往的将p变成下一个结点 
	}
	q=(Liststruct *)malloc(sizeof(Liststruct));		///创建新结点并分配空间(这个结点就是用来插入字符的) 
	q->book=ch;							///将q的book赋值为ch(将字符放入结点内)
	if(k==1){					///这个if else实际上是可以不加的(我认为上一个while循环已经包含了这个k==1的情况) 
		Head->next=q;			///这一步其实就是插入结点
		q->next=p;
	}
	else{
		t->next=q;				///将前一个结点的指针域的指针指向q的地址 
		q->next=p;				///将q的指针域指向下一个结点的地址(从中间接入一个结点,字符插入完成) 
	}
	Head->Length++;			///别忘了将链表的总长度加1哦 
	return ;
}

//删除第k个元素
void DATA_Delete(ListHead *Head,int k)		///定义void类型函数 参数是结构体指针Head和int类型变量k(位置)
{
	if(k<1 || Head->Length<k){						///同样首先判断链表中有无这个位置 
		cout << "警告!不存在第" << k << "位置元素" << endl;
		return ;
	}
	Liststruct *p=Head->next,*t;			///一如既往的定义指针 指针p,前指针t 
	int i=1;
	while(p && i++!=k){						///一如既往的寻找k这个位置所对应的结点
		t=p;								///将上一个结点保留在t 
		p=p->next;							///一如既往的将p变成下一个结点
	}
	if(k==1){						///这个是将结点删除(其实是将该结点跳过) 
		Head->next=p->next;
	}
	else{
		t->next=p->next;			///将t的指针域的指针指向p的指针所指向的(将p结点跳过) 
	}
	free(p);						///跳过后将p释放,就是将该结点删除了 
	Head->Length--;					///记得将链表总长度减1哦 
	return ;
}

//逆置链表
void DATA_UN(ListHead *Head)		///定义void类型函数 参数是结构体指针Head
{
	Liststruct *p,*q;			///一如既往的定义指针 指针p,q 
	p=Head->next;			///将p赋值为Head的next(指针域),和*p=Head->next的区别是? 
	Head->next=NULL;		///将Head的next置空 
	while(p!=NULL){
		q=p;				///将p赋值给q(p代表的到底是结点还是什么?) 
		p=p->next;			/// 将p所指向的结点地址赋值给p
		q->next=Head->next;			///将Head的next赋值给q的next 
		Head->next=q;		///将q赋值给Head的next(这个赋值的是q结点的首地址?) 
	}
	return ;
}

//返还内存
void List_FREE(ListHead *Head)		///定义void类型函数 参数是结构体指针Head
{
	Liststruct *p=Head->next,*q;	///定义Liststruct类型的结构体指针,并指向Head->next;指针q 
	free(Head);					///释放Head 
	while(p){
		q=p;					///...
		p=p->next;				///p的next赋值给p 
		free(q);				///将q释放 
	}
	return ;
} 

int main()
{
	ListHead *Head;			///创建一个头结点 头指针 首元结点(还没搞清楚) 
	Numelem i;				///定义int型变量i 
	Excelelem ch;			///定义char型变量ch 
	puts("");				///输出一个空字符串? 
	puts("******等待链表Head初始化!******"); 
	Head=Headinit();		///调用函数初始化一个链表	
	puts("******链表Head初始化完成!******");
	cout << "链表中的内容为:" << endl;
	DATA_cout(Head);		///调用函数输出链表
	cout << "链表Head的长度为:" << endl;
	cout << Head->Length << endl;	///输出链表长度 
	///cin >> i;
	//cout << "链表第" << i=2 << "个元素是:" << endl;		///这个i可以用输入流控制值
	i=2; 
	cout << "链表第" << i << "个元素是:" << endl;		///上面的出问题了,不知道为什么 
	Local(Head,i);			///调用函数找到元素 
	///cin >> ch;
	//cout << "链表中出现" << ch='6' << "元素的位置分别是:" << endl;	///同i 
	ch='6';
	cout << "链表中出现" << ch << "元素的位置分别是:" << endl;	///上面的出问题了,不知道为什么
	DATA_find(Head,ch);		///调用函数找到位置 
	///cin >> i >> ch;
	//cout << "在链表的第" << i=4 << "个元素之前插上" << ch='9' << endl; ///同i,ch 
	i=4;
	ch='9';
	cout << "在链表的第" << i << "个元素之前插上" << ch << endl;	///上面的出问题了,不知道为什么
	DATA_Insert(Head,i,ch);	///调用函数传递参数执行 添加元素 
	cout << "链表中的内容为:" << endl;
	DATA_cout(Head);		///调用函数输出链表
	///cin >> i;
	//cout << "将链表中第" << i=3 <<"个元素删除" << endl;		///同上 
	i=3;
	cout << "将链表中第" << i <<"个元素删除" << endl;	///上面的出问题了,不知道为什么
	DATA_Delete(Head,i);	///调用函数删除元素 
	cout << "链表中的内容为:" << endl;
	DATA_cout(Head);		///调用函数输出链表
	cout << "将链表所有元素逆置,请稍后..." << endl << endl;  //多种方法
	DATA_UN(Head);			///调用函数逆置链表 
	cout << "链表中的内容为:" << endl;
	DATA_cout(Head);		///调用函数输出链表
	puts("******链表Head使用完毕!******\n");
	List_FREE(Head);		///调用函数释放链表 
	return 0;
}

代码源自
https://blog.csdn.net/calculate23/article/details/79758845
仅以此博客记录我学习数据结构链表时对链表代码的理解
暂时还没能力独自编写链表…
记在博客上方便随时看
注释多为我个人理解
在这里插入图片描述

链表-4

这是链表的第四次练习了,代码有一些问题
就是判断空的时候判断不了

#include<iostream>
#include<cstdlib>
using namespace std;

//指针就是它所指向的那个变量的地址 

//链表,第一步 定义结构体,结点类型,结点实际上就是一个一个结构体 
typedef struct LinkList {
	char book;
	struct LinkList *next;
}LinkList;

//表头
typedef struct {
	int book[100];
	LinkList *next;
	int Length;	
}ListHead;

//第二步,初始化链表
LinkList *init(int *i) {		//*i 链表长度 
	LinkList *Head,*p,*q;
	char ch;
	Head = q = NULL;
	cout << "请输入链表的内容:" << endl;
	//system("pause");
	getchar();	//让系统暂停一下
	while((ch = getchar()) != '\n') {
		p = (LinkList *)malloc(sizeof(LinkList));
		p->book = ch;
		if(!(*i)) {
			Head = q = p;
			(*i)++;
		}
		else {
			q->next = p;
			q = p;	//p有新分配的空间,而q只是个指针,让指向哪就指向哪
			(*i)++; 
		}
	}
	if(q) q->next = NULL;	//要不然指向的是q本身
	system("pause");
	return Head;	//返回值类型和函数类型一样,可以理解为是LinkList *类型,也可以理解为LinkList类型的指针,一个意思 
}

ListHead *Headinit() {
	ListHead *Head;
	Head = (ListHead *)malloc(sizeof(ListHead));
	Head->Length = 0;
	Head->next = init(&Head->Length);	//借助地址返回
	return Head;
}

//打印表
void Data_cout(ListHead *Head) {		//包括以下函数都是利用头结点找到链表 
	LinkList *p = Head->next;
	while(p != NULL) {
		cout << p->book << " ";
		p = p->next;
	}
	cout << endl;
	return ;	//可以不写 
}

//定位位置元素
void Data_position(ListHead *Head,int local) {
	if(local < 1 || local > Head->Length) {	//规定位置从1开始 
		cout << "ERROR! NOT FOUND LOCAL!" << endl;
		return ;	//这个不能省,不写的话程序就继续执行了 
	}
	LinkList *p = Head->next;
	/*for(int i = 0;i < Head->Length;i++) {	//条件换成p也行 
		if(p && i+1 == local) {
			cout << local << "位置元素为:" << p->book << endl;
			break;
		}
		p = p->next;
	}试一试 用for循环的方法*/
	int i = 1;
	while(p && i++ != local)
		p = p->next;
	cout << local << "位置元素为:" << p->book << endl;
	return ;	//可以省,后面的只要不说就是可以省略的 
}

//定位元素位置
void Data_find(ListHead *Head,char ch) {
	LinkList *p = Head->next;
	int i = 1,flag = 0,count = 1;
	/*for(i = 0;i < Head->Length;i++) {
		if(p && p->book == ch) {
			flag = 1;
			cout << p->book << "元素在第:" << i+1 << "位置" << endl;
			break;
		}
		p = p->next;
	}*/
	while(p) {
		if(p->book == ch) {
			flag = 1;
			cout << count++ << "." << p->book << "元素出现在第:" << i << "位置" << endl;
		}
		p = p->next;
		i++;
	}	
	if(!flag) {
		cout << "ERROR! NOT FOUND " << ch << endl;
	}
	return ;
	
}

//插入元素
void Data_insert(ListHead *Head,int k,char ch) {
	if(k < 1 || k > Head->Length) {
		cout << "WARNING! NOT FOUND " << k << endl;
		return ;	//不能省 
	}
	LinkList *p = Head->next,*q,*t;
	/*for(i = 0;p;i++) {
		t = p;
		p = p->next;
		if(k == 1) {
			Head->next = q;
			q->next = p;
		}
		else if(p && i+1 == k) {
			q->next = p;
			t->next = q;
		}
		p = p->next;
	}用for和用while没多大差别。。。*/
	int i = 1;
	while(p && i++ != k) {
		t = p;
		p = p->next;
	}
	q = (LinkList *)malloc(sizeof(LinkList));
	q->book = ch;
	if(k == 1) {
		Head->next = q;
		q->next = p;
	}
	else {
		q->next = p;
		t->next = q;
	}
	Head->Length++;
	return ;
}

//删除元素
void Data_delete(ListHead *Head,int k) {
	if(k < 1 || k > Head->Length) {
		cout << "WARNING! NOT FOUND " << k << endl;
		return ;	//不能省
	}
	int i = 1;
	LinkList *p = Head->next,*q;
	while(p && i++ != k) {
		q = p;
		p = p->next;
	}
	if(k == 1) {
		Head->next = p->next;
	}
	else {
		q->next = p->next;
	}
	free(p);
	Head->Length--;
	return ;
}

//逆置表
void Data_un(ListHead *Head) {
	LinkList *p = Head->next,*q;
	Head->next = NULL;
	while(p != NULL) {
		q = p;
		p = p->next;
		q->next = Head->next;
		Head->next = q;
	}
	return ;
}

//返还内存
void List_free(ListHead *Head) {
	LinkList *p = Head->next,*q;
	free(Head);
	while(p) {
		q = p;
		p = p->next;
		free(q);	//要是直接释放p的话,然后就没有然后了 
		q = NULL;
	}
}

void Menu() {
	cout << "*** 1.---初始化链表 ***" << endl;
	cout << "*** 2.---打印表 ***" << endl;
	cout << "*** 3.---定位位置元素 ***" << endl;
	cout << "*** 4.---定位元素位置 ***" << endl;
	cout << "*** 5.---插入元素 ***" << endl;
	cout << "*** 6.---删除元素 ***" << endl;
	cout << "*** 7.---逆置表 ***" << endl;
	cout << "*** 8.---返还内存 ***" << endl;
	cout << "*** 0.---退出 ***" << endl;
	cout << endl;
}

int main()
{
	int i;
	char ch;
	puts("");
	int mark = 1;
	Menu();
	while(mark) {
		//system("cls");	//清屏 
		cout << "enter:" << " ";
		int select;
		cin >> select;
		switch(select) {
			case 1:
				ListHead *Head;
				puts("******等待链表Head初始化!******");
				Head = Headinit();
				puts("******链表Head初始化完成!******");
				break;
			case 2:
				puts("******链表中的内容为: ******");
				Data_cout(Head);
				puts("******链表Head的长度为: ******");
				cout << Head->Length << endl;
				break;
			case 3:
				puts("******请输入位置(i): ******");
				cin >> i;
				cout << "链表第" << i << "个元素是: ";
				Data_position(Head,i);
				break;
			case 4:
				puts("******请输入元素(ch): ******");
				cin >> ch;
				cout << "链表中出现" << ch << "元素的位置分别是: " << endl;
				Data_find(Head,ch);
				break;
			case 5: 
				puts("******请输入要插入位置(i): ******");
				cin >> i;
				puts("******请输入要插入元素(ch): ******");
				cin >> ch;
				Data_insert(Head,i,ch);
				puts("******插入完成!******");
				break;
			case 6:
				puts("******请输入删除位置(i): ******");
				cin >> i;
				Data_delete(Head,i);
				puts("******删除完成!******");
				break;
			case 7:
				Data_un(Head);
				puts("******逆置完成!******");
				break;
			case 8:
				List_free(Head);
				puts("******释放完毕!******");
				break;
			case 0:
				mark = 0;
				break;
		}
	}
} 

反复强调!!!一定要看啊啊啊!!!老是没时间看写过的博客,这可不行。。。
运行结果:
在这里插入图片描述

在这里插入图片描述

最初的单链表

最原始的那个
书上代码有一些错误,主要是理解链表函数

#include<iostream>
#include<cstdlib>
#include<cstring>
using namespace std;

struct Node {
	int data;
	struct Node *next;
}; 

typedef struct Node Node;
typedef struct Node * Link;
char menu();
void create(Link);
void show(Link);
int find(Link,int);
void insert(Link,int,int);
void del(Link,int);

int main()
{
	int leave =0;
	Link head = (Link)malloc(sizeof(Node));
	create(head);
	do {
		int num,index;
		char n = menu();
		switch(n) {
			case '1':
				cout << "请输入要插入的数值:";
				cin >> num;
				cout << "请输入要插入的位置:";
				cin >> index;
				insert(head,index,num);
				show(head);
				break;
			case '2':
				cout << "请输入要删除的位置:";
				cin >> index;
				del(head,index);
				show(head);
				break;
			case '3':
				cout << "请输入要查找的数值;";
				cin >> num;
				find(head,num); 
				break;
			case '4':
				show(head);
				break;
			case '5':
				leave = 1;
				break;
		}
	}while(leave == 0);
	return 0;
}

char menu() {
	char select[100];
	cout << "***   单链表   ***" << endl;
	cout << "*** 1.插入结点 ***" << endl;
	cout << "*** 2.删除结点 ***" << endl;
	cout << "*** 3.查找结点 ***" << endl;
	cout << "*** 4.显示链表 ***" << endl;
	cout << "*** 5.退出系统 ***" << endl;
	cout << "请选择:" << endl;
	do {
		fflush(stdin);		//???
		gets(select);
		if(strlen(select) == 1) {
			if(strcmp(select,"1") == 0 || strcmp(select,"2") == 0 || strcmp(select,"3") == 0 || strcmp(select,"4") == 0 || strcmp(select,"5") == 0) {
				return select[0];
			}		//这是啥??? 
		}
		cout << "输入有误!" << endl;  
	}while(1);
}

//创建 
void create(Link head) {
	int i = 0;
	Link q = head;
	while(i < 5) {	//共输入5个结点 
		Link p = (Link)malloc(sizeof(Node));	//p指向下一个结点
		p->data = (i+1) * 10;
		p->next = NULL;	//先让p的next指向NULL是什么操作?就可以循环输入了 
		p->next = q->next;	//这句话书上是不是少了? 
		q->next = p;
		q = p;
		i++;
	}
}

//遍历输出 
void show(Link head) {
	Link p = head->next;
	while(p != NULL) {
		cout << p->data << " ";
		p = p->next;
	}
	cout << endl;
}

//定位元素位置 
int find(Link head,int num) {
	int i = 1;
	Link p = head->next;
	while(p != NULL) {
		if(p->data == num) {
			cout << "第" << i << "个结点!" << endl;
			return i;
		}
		i++;
		p = p->next;
	}
	cout << "没找到!" << endl;
	return 0;
}

//插入 
void insert(Link head,int index,int num) {
	int i = 1;
	Link p = head;
	Link pnew = (Link)malloc(sizeof(Node)); 	//pnew指向新结点
	pnew->data = num;
	pnew->next = NULL;
	if(index < 0) {
		cout << "插入位置有误!" << endl;
		return;
	}
	while(p != NULL) {
		if(i == index) {
			break;
		}
		p = p->next;
		i++;
	}
	if(p == NULL) {
		cout << "插入位置有误!" << endl;
		return;
	}
	pnew->next = p->next;
	p->next = pnew;
}

//删除
void del(Link head,int index) {
	int i = 1;
	Link q = head;
	Link p = q->next;
	if(index <= 0) {
		cout << "删除位置有误!" << endl;
		return;
	}
	while(p != NULL) {
		if(i == index) {
			break;
		}
		q = p;
		p = p->next;
		i++;
	}
	if(p == NULL) {		//这是循环到了最后一个结点的后面 
		cout << "插入位置有误!" << endl;
		return;
	}
	q->next = p->next;
	free(p);
} 


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值