C加加链表之基础单链表实现

链表构成和实现

链表是由一群结点(node)所组成的链式结构

其中单链表的每一个节点可以顺次找到下一个节点 如图

其中节点是结构体,由两个部分组成,存数据的(数据域)和存指向下一个节点的地址的(指针域)

#include <iostream>
using namespace std;
struct Node 
{
    int data;
    struct Node* next;
};

创建一个节点并打印其数据域试一试

int main()
{
    struct Node node1 = { 10,NULL };
    cout << node1.data;
return 0;
}

结果为10

现在我们按第一个图多创造几个节点并且连接起来,并测试连接性

int main()
{
    struct Node node1 = { 10,NULL };
    struct Node node2 = { 11,NULL };
    struct Node node3 = { 12,NULL };
    node1.next = &node2;
    node2.next = &node3;
    cout << node1.next << " " << node2.next;
return 0;
}

结果如图

链表的打印

现在我们试着打印整个链表的数据域

int main()
{
    struct Node node1 = { 10,NULL };
    struct Node node2 = { 11,NULL };
    struct Node node3 = { 12,NULL };
    node1.next = &node2;
    node2.next = &node3;

    struct Node* pMove = &node1;//创造一个可以移动的结构体指针pMove,并初始化使其指向node1(节点1)
    while (pMove != NULL)//当pMove指向的节点的地址非空即节点存在时
    {
        cout << pMove->data<<" ";//当pMove本身是指针时可以用pMove->data表示pMove指向节点的数据域
        pMove = pMove->next;//pMove->next是pMove对应的节点存储的指针域(下一个节点的地址)
    }
return 0;
}

运行结果

现在我们试着实现一些插入的功能

首插法

首先我们先设计一个创建新节点的函数

struct Node* createNewNode(int data)
{
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));//sizeof是求Node结构体的大小,与结构体Node里的内容,类型多少有关,malloc()是动态内存分配函数,(struct Node*)再将返回值修改成结构体指针,newnode是一个创造出的结构体指针其对应一个创造出的结构体
        newNode->data=data;
        newNode->next = NULL;
        return newNode;//返回newnode的地址即新创造的结构体的地址
}

然后我们开始进行链表的插入,首先试试往10 11 12前面插入7 8 9(首插法)

这个时候我们遇到了一个问题如果只插入9那么如下函数即可实现

void insertNodeByHead(struct Node* firstnode,int data) 
{
    struct Node* newNode = createNewNode(data);
    newNode->next = firstnode;
}

但是这时我们不知道刚插入的9对应的节点名,无法表示首节点的地址和打印函数并且难以实现在9前面再插入8

所以我们在头结点前加入一个表头ListHead,那么首节点就一直是表头,这时问题即可解决

struct Node* listHeadNode = (struct Node*)malloc(sizeof(struct Node));//创建表头,malloc函数上面解释过
        listHeadNode->next = &node1;//指针域指向node1

我们将首插法修改成

void insertNodeByHead(struct Node* ListHeadNode,int data) 
{
    struct Node* newNode = createNewNode(data);
    newNode->next = ListHeadNode->next;//这时ListHeadNode->next代表的是node1;
    ListHeadNode->next = newNode;//这个时候ListHeadNode->next代表的是newNode
}

将原有打印代码封装成函数

void printList(struct Node* listHeadNode)
{
    struct Node* pMove = listHeadNode->next;
    while (pMove != NULL)
    {
        cout << pMove->data << " ";
        pMove = pMove->next;
    }
}

至此我们可以实现可以将 7 8 9 插入到原有的10 11 12链表中,代码如下

#include <iostream>
using namespace std;
struct Node 
{
    int data;
    struct Node* next;
};
struct Node* createNewNode(int data)
{
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    newNode->data = data;
    newNode->next = NULL;
    return newNode;
}
//首插法
void insertNodeByHead(struct Node* ListHeadNode,int data) 
{
    struct Node* newNode = createNewNode(data);
    newNode->next = ListHeadNode->next;
    ListHeadNode->next = newNode;
}
void printList(struct Node* listHeadNode)
{
    struct Node* pMove = listHeadNode->next;
    while (pMove != NULL)
    {
        cout << pMove->data << " ";
        pMove = pMove->next;
    }
}
int main()
{
    struct Node node1 = { 10,NULL };
    struct Node node2 = { 11,NULL };
    struct Node node3 = { 12,NULL };
    node1.next = &node2;
    node2.next = &node3;
    
        struct Node* listHeadNode = (struct Node*)malloc(sizeof(struct Node));
        listHeadNode->next = &node1;
        insertNodeByHead(listHeadNode, 9);
        insertNodeByHead(listHeadNode, 8);
        insertNodeByHead(listHeadNode, 7);
        printList(listHeadNode);
        return 0;
    
}
    

运行结果

尾插法

void insertNodeByTail(struct Node* ListHeadNode, int data) 
{
    struct Node* newNode = createNewNode(data);
    struct Node* pMove =ListHeadNode ;
    while (pMove->next) 
    {
        pMove = pMove->next;
    }
    
    pMove->next = newNode;
    newNode->next = NULL;
}

插入13 14 15

        insertNodeByTail(listHeadNode, 13);
        insertNodeByTail(listHeadNode, 14);
        insertNodeByTail(listHeadNode, 15);

运行结果

指定插入法

将node3的值改成13便于理解

struct Node node3 = { 13,NULL };

此时为10 11 13

将12插在11 和13之间

void insertNodeByappointed(struct Node* listHeadNode, int data, int posData)
{
    struct Node* posNodeFront = listHeadNode;//缩写成PF
    struct Node* posNode = listHeadNode->next;//缩写成P
    struct Node* newNode = createNewNode(data);//这时PF为表头,P为第一个节点,
    if (posNode == NULL)
    {
        cout << "链表为空";
        system("pause");
    }//检查链表是否为空
    else 
    {
        while (posNode->data != posData) 
        {
            posNodeFront = posNode;
            posNode = posNode->next;
            if(posNode==NULL)
                {
                cout << "未找到相关信息";
                system("pause");
                return ;//返回值不存在为空,仅表示退出程序
                }//检查是否存在指定值
        }
        
        posNodeFront->next = newNode;
        newNode->next = posNode;//将newNode插在PF和P之间
    }
}

运行结果

首删法

void deleteNodeByHead(struct Node* listHeadNode)
{
    struct Node* deleteNode = listHeadNode->next;
    listHeadNode->next = deleteNode->next;
    deleteNode = NULL;//置空,否则free函数可能会报错
    free(deleteNode);
    
}

尾删法

void deleteNodeByTail(struct Node* listHeadNode) {

    struct Node* pMove = listHeadNode;
    struct Node* pMoveFront = NULL;

    while (pMove->next)
    {
        pMoveFront = pMove;
        pMove = pMove->next;
    }
    pMove = NULL;
    free(pMove);
    pMove = NULL;//置空,防止野指针
    pMoveFront->next = NULL;

}

指定位置删除

void deleteNodeByAppointed(struct Node* listHeadNode,int posData)
{
    struct Node* posNodeFront = listHeadNode;//缩写成PF
    struct Node* posNode = listHeadNode->next;//缩写成P

    if (posNode == NULL)
    {
        cout << "链表为空";
        system("pause");
    }//检查链表是否为空
    else
    {
        while (posNode->data != posData)
        {
            posNodeFront = posNode;
            posNode = posNode->next;
            if (posNode == NULL)
            {
                cout << "未找到相关信息";
                system("pause");
                return;//返回值不存在为空,仅表示退出程序
            }//检查是否存在指定值
        }
        posNodeFront->next = posNode->next;
        posNode = NULL;
        free(posNode);
        posNode = NULL;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值