您的位置:首页 > 其它

<3> 单链表的各种操作(创建、增加、删除、修改、查找、逆序、判空、置空等)

2017-09-30 14:46 771 查看
1 . 链表的创建

1)首先声明三个结构体指针变量(head、p1、p2),其中,一个是头结点,剩余的两个用来连接。

2)给p1开辟内存空间,代表第一个结点的地址,并且给第一个结点的数据域中的数据赋值。



3)循环创建(假设有N个结点需要创建)的过程。需要分情况,当我们的头结点并没有被连接到任何创建的结点上时,需要将head连接到,同时需要将p2也指向p1,这是因为当我们在将head连接上之后,之后的连接就需要p2和p1来进行完成,不需要head了。如下图:



这是在循环创建时的几个过程。记得每开辟一个空间,需要给结构体中的数据赋值,即每一个结点赋值。

4)创建结束后,需要将p2的指针域指向NULL,代表整个链表结束,并且记得释放p1,因为p1的作用仅仅是为我们创建新的结点。

2 . 判空

链表的最后一个指针域是指向NULL的,所以我们只需要判断head是不是指向NULL即可,如果是,代表链表是空的,如果不是,代表链表有数据。

3 . 置空

同样,我们需要将头指针指向NULL即可。

4 . 删除



如图想要把中间的结点删除,需要将第一个结点的指针域指向第三个结点的地址,就可以实现在链表中将第二个结点删除。

5 . 增加、修改、逆序等见代码的详解。

6 . 详细代码

1)Head.h文件

#pragma once

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <iostream>

//! \brief 一个关于“学生”的结构体类型
typedef struct Student
{
// 数据域(存储数据)
int  _age;				//!< 年龄
char _name[20];			//!< 姓名
char _gender;			//!< 性别

// 指针域(存储下一个节点的地址)
Student *next;
}LinkList;

/*
这里是一些基本的链表操作的函数声明
*/

// 创建一个链表
LinkList* create(unsigned int Number);

// 判断链表是否为空
bool IsEmpty(LinkList L);

// 将链表置空
void MakeLinkList(LinkList L);

// 根据值查询位置
// 1:年龄 2:名字 3:性别
int Find1(LinkList *L, int Age);
int Find2(LinkList *L, char *Name);
int Find3(LinkList *L, char Gender);

// 删除某个节点
bool Delete(LinkList *L, char *Name);

// 增加一个节点
bool Push_Back(LinkList *L, LinkList *LNew);

// 修改一个节点
bool Modify(LinkList *L, char *Name);

// 打印整个链表
void PrintLinkList(LinkList* L);

// 逆序整个链表
LinkList* Reverse(LinkList *L);
2)Source.cpp文件

#include "Header.h"

/*
这里是一些基本的链表操作的函数实现
*/

LinkList* create(unsigned int Number)
{
// 声明三个结构体( 其中head是头节点,p1为临时节点,p2是辅助节点 )
LinkList *head, *p1 = NULL, *p2 = NULL;

// 使得P1、P2指向空间大小为sizeof(LinkList)的内存空间
p1 = (LinkList*)malloc(sizeof(LinkList));

// 初始化head为NULL
head = NULL;

// 初始化第一个节点的数据
std::cin >> p1->_name >> p1->_age >> p1->_gender;

// 循环创建、连接、初始化数据
for (size_t i = 0; i < Number - 1;)
{
// 连接节点
if (head == NULL)
{
head = p1;
p2 = p1;
}
else
{
// 创建新的节点,并初始化新的节点
p1 = (LinkList*)malloc(sizeof(LinkList));
//scanf_s("%s %d %c", &p1->_name, &p1->_age, &p1->_gender);
std::cin >> p1->_name >> p1->_age >> p1->_gender;

p2->next = p1;
p2 = p1;

// add
i++;
}
}

// 使p2->next指向空,代表链表结束
p2->next = NULL;

// 释放临时的p1
p1 = NULL;
free(p1);

return head;
}

bool IsEmpty(LinkList L)
{
return L.next == NULL;
}

void MakeLinkList(LinkList L)
{
L.next = NULL;
}

int Find1(LinkList *L, int Age)
{
int Location = 0;
LinkList *P = L->next;
while (P!= NULL&&P->_age != Age)
{
P = P->next;
Location++;
}

return Location;
}

int Find2(LinkList *L, char *Name)
{
int Location = 0;
LinkList *P = L;
while (P!= NULL&&strcmp(P->_name,Name))
{
P = P->next;
Location++;
}

return Location;
}

int Find3(LinkList *L, char Gender)
{
int Location = 0;
LinkList *P = L->next;
while (P!=NULL&&P->_gender != Gender)
{
P = P->next;
Location++;
}

return Location;
}

bool Delete(LinkList *L, char *Name)
{
// 两个临时的指针,其中第一个指针是保存目标节点的上一个节点
LinkList *TempPointer1 = L;
LinkList *TempPointer2 = NULL;

while (strcmp(TempPointer1->_name,Name) && TempPointer1 != NULL)
{
TempPointer2 = TempPointer1;
TempPointer1 = TempPointer1->next;
}

if (TempPointer1 != NULL)
{
TempPointer2->next = TempPointer1->next;
return true;
}

return false;
}

bool Push_Back(LinkList *L, LinkList *LNew)
{
// 将LNew加到L中
// 尾插
while (L!=NULL)
{
if (L->next == NULL)
{
L->next = LNew;
break;
}

L = L->next;
}

return true;
}

bool Modify(LinkList *L, char *Name)
{
while (strcmp(L->_name,Name) && L!=NULL)
{
L = L->next;
}

if (L != NULL)
{
L->_age = 100;
L->_gender = 'm';

return true;
}

return false;
}

void PrintLinkList(LinkList *L)
{
while (L!=NULL)
{
std::cout << L->_name << " " << L->_age << " " << L->_gender << std::endl;
L = L->next;
}
}

LinkList* Reverse(LinkList *L)
{
LinkList *PreLinkList = NULL;
LinkList *Next;

while (L!=NULL)
{
Next = L->next;
L->next = PreLinkList;
PreLinkList = L;
L = Next;
}

return PreLinkList;
}
3)main.cpp文件

#include "Header.h"

int main()
{
// 初始化并打印
//
a242
----------------------------------------------------------------
LinkList* head = create(3);

std::cout << "Origin : " << std::endl;
PrintLinkList(head);

// 我是分割线
std::cout << "-----------------------------------------------------" << std::endl;

// 1 . 增
//----------------------------------------------------------------
LinkList* NewLinkedList = create(2);
Push_Back(head, NewLinkedList);

std::cout << "Added : " << std::endl;
PrintLinkList(head);

// 我是分割线
std::cout << "-----------------------------------------------------" << std::endl;

// 2 . 删
//----------------------------------------------------------------
Delete(head, "test2");

std::cout << "Deleted : " << std::endl;
PrintLinkList(head);

// 我是分割线
std::cout << "-----------------------------------------------------" << std::endl;

// 3 . 改
//----------------------------------------------------------------
Modify(head, "test1");

std::cout << "Modified : " << std::endl;
PrintLinkList(head);

// 我是分割线
std::cout << "-----------------------------------------------------" << std::endl;

// 4 . 查
//----------------------------------------------------------------
int Location = Find2(head, "test1");
std::cout << "Finded : " << Location << std::endl;

// 我是分割线
std::cout << "-----------------------------------------------------" << std::endl;

// 5 . 逆
LinkList* New = Reverse(head);

std::cout << "Resversed : " << std::endl;
PrintLinkList(New);

std::cout << "---------------------Finished------------------------" << std::endl;
system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐