数据结构——链表

因为教材是用的C++,所以今天的代码是用C++实现的

//单链表的定义
typedef struct LNode
{
	ElemType data;
	struct LNode *next;
}LNode,*LinkList;

//初始化
Status InitList(LinkList &L)
{
	L=new LNode;
	L->next=NULL;
	return OK;
}

//取值
Status GetElem(LinkList L ,int i,ElemType &e){
	p=L->next;;
	j=1;
	while(p&&jnext;
		++j;
	}
	if(!p||j>i)return ERRPR;
	e=p->data;
	return OK;
	
}

//查找
LNode *LocateElem(LinkList L,ElemType e){
	p=L->next;
	while(p && p->data!=e)
		p=p->next;
	return p;
}

//插入
Status ListInsert(LinkList &L,int i,ElemType e){
	p=L;
	j=0;
	while(p && (jnext;
		++j;
	}
	if(!p||j>i-1) return ERROR;
	s=new LNode;
	s->data=e;
	s->next=p->next;
	p->next=s;
	return OK;
}

//删除
Status ListDelete(LinkList &L,int i){
	p=L;
	j=0;
	while((p->next) && (jnext;
	}
	if(!(p->next)||j>i-1) return ERROR;
	q=p->next;
	p->next=q->next;
	delete q;
	return OK;
}

//前插法创建单链表
void CreateList_H(LinkList &L,int n){
	L=new LNode;
	L->next=NULL;
	for(i=0;i>p->data;
		p->next=L->next;
		L->next=p;
	}
}

//后插法创建单链表
void CreateList_R(LinkList &L,int n){
	L=new Lnode;
	L->next=NULL;
	r=L;
	for(i=0;i>p->data;
		p->next=NULL;
		r->next=p;
		r=p;
	}
}



//循环链表的定义及初始化
typedef struct LNode
{
	ElemType data;
	struct LNode *next;
}LNode,*LinkList;

Status InitList(LinkList &L)
{
	L=new LNode;
	L->next=L;    //只有这里跟单链表不同,其余地方都一样
	return OK;
}



//双向链表的定义及初始化
typedef struct DuLNode{
	ElemType data;
	struct DuLNode *prior;
	struct DuLNode *next;
}DuLNode,*DuLinkList;

Status InitList(DuLinkList &L){
	L=new DuLNode;
	L->next=L;
	L->prior=L;
	return OK;
}


//双向链表的插入
Status ListInsert_DuL(DuLinkList &L,int i,ElemType e){
	if(!(p=GetElem_Dul(L,i)))
		return ERROR;
	s=new DuLinkList;
	s->data=e;
	a=p->prior;
	p->prior=s;
	s->prior=a;
	a->next=s;
	s->next=p;
	return OK;
}

//双向链表的删除
Status ListDelete_DuL(DuLinkList &L,int i){
	if(!(p=GetElem_Dul(L,i)))
		return ERROR;
	p->next->prior=p->prior;
	p->prior->next=p->next;
	delete p;
	return OK;
}

链表的工作原理

在一个链表中,每个节点都有一个 next 指针,指向下一个节点。例如,假设有两个节点:

LNode *node1 = new LNode;
LNode *node2 = new LNode;

node1->next = node2; // node1 的 next 指向 node2

在这个例子中,node1next 指向 node2,表示链表中的第一个节点指向第二个节点。通过这种方式,节点可以连接起来,形成一个链表。

动态创建新的节点

这行代码 LNode *node1 = new LNode; 的意思是动态创建一个新的 LNode 类型的节点,并将其地址赋值给指针 node1

new LNode

  • new 是一个运算符,用于在堆上动态分配内存。
  • LNode 表示你要创建一个新的 LNode 结构体实例。这段代码会在堆上分配足够的内存来存储一个 LNode 的数据,并返回这个新创建对象的地址

初始化

  • 函数定义:​​​​​​

    • ​​​​Status InitList(LinkList &L): 这是函数的声明,函数名为 InitList,返回类型为 Status(表示操作的状态,如成功或失败),接受一个引用类型的参数 LinkList &L。这里的 LinkList 是指向 LNode 的指针类型。

  • 创建新的节点

    • L=new LNode;: 这一行代码使用 new 关键字在堆上动态分配一个新的 LNode 结构的内存,并将这个新节点的地址赋值给 L。这意味着 L 现在指向一个新的链表节点。

  • 初始化 next 指针

    • L->next=NULL;: 将新节点的 next 指针设置为 NULL,表示当前链表中只有一个节点(头节点),而且没有后继节点。链表的末尾通常用 NULL 来表示。

  • 返回状态

    • return OK;: 函数结束时返回一个状态值 OK,表示链表成功初始化。

引用类型

  1. LinkList:这是一个指向 LNode 类型的指针(即 LNode* 的别名)。
  2. &L:表示 LLinkList 类型的引用。这意味着 L 引用的是一个指向 LNode 的指针。

在 C++ 中,引用是一种特殊的变量,它允许你直接访问另一个变量的内存,而不是创建该变量的副本。当你使用引用作为参数时,函数可以直接操作传入的变量,而不需要返回值来修改它。(可以对比上个笔记C语言的访问创建副本)

举个例子

假设你有一个函数:

void modify(int &x) {
    x = 10; // 修改了引用变量 x
}

void modify(int &x) 中,x 是一个 int 类型的引用。这意味着:

  1. 引用的性质x 并不是一个新的变量,而是直接引用了传入的整型变量。换句话说,x 是传入整型变量的别名。

  2. 改变引用的值:当你在 modify 函数中对 x 进行修改时,实际上是在修改传入的那个整型变量。因此,任何对 x 的改变都会直接影响到原始的变量。

如果你调用这个函数:

int a = 5;
modify(a); // a 现在变为 10
C++的引用相较于C语言指针的一些优势:
1. 语法简洁

引用的语法更简洁,因为你不需要使用解引用操作符(*)来访问引用的变量。

2. 避免空指针

引用必须在定义时初始化,并且不能为 NULL(或 nullptr)。这意味着引用始终指向一个有效的对象,而指针可能指向 NULL,从而引发潜在的空指针异常。

3. 更自然的语义

引用更像是对变量的别名,能够更清晰地表达意图。在许多情况下,使用引用的代码更易读,更容易理解。

4. 简化参数传递

在函数参数中使用引用,可以直接修改传入的变量,而不需要返回值。

取值

关于 L 的含义

在代码中:

  • L 是整个链表的“入口”,也就是头指针。
  • 头指针 L 通常指向一个特殊的 头节点(dummy node)。头节点本身不存储实际的数据,只是为了方便操作整个链表,比如插入、删除和遍历等。
  • L->next 指向链表的第一个有效节点(首元节点)。
  • 如果链表为空,L->next == NULL

e = p->data 的意义

假设 p 当前指向第 i 个节点:

  • p->data 表示这个节点中存储的 数据部分
  • 赋值语句 e = p->data 将该节点的数据部分赋值给变量 e

为什么 p->data 可以访问数据?

这是因为 p 是一个指向节点的指针,p->data 表示指针所指向节点的 data 成员。

查找 

LNode *LocateElem

LNode *LocateElem(LinkList L, ElemType e)

LNode * 表示LocateElem函数返回的是一个指向链表节点的指针。

前插法创建单链表

cin>>p->data;

>> 是 C++ 中的输入运算符。它是从标准输入(通常是键盘)中读取数据的方式之一。

  • 在 C++ 中,>>流提取运算符(stream extraction operator)。
  • 它用于从输入流中提取数据,并将数据存储到指定的变量中。
  • cin 是 C++ 的标准输入流对象,通常用于从键盘获取输入。

你可能感兴趣的:(数据结构)