链表笔记。(单向,双向,初始化,插入,删除,遍历)

笔记是去年写的了,然后最近年终总结回顾了一下,发现全是漏洞,就把代码练习那部分修改完善了一些,其他部分应该是当时随便copy的,就没怎么看。重点是练习部分,包含了所有使用情况。先暂时传上来吧。

链表

单向链表

链表的结构类型

typedef struct LinkList                             
{
         int Element;
         LinkList * next;
}LinkList;

链表内包含很多结点。其中每个结点的数据空间一般会包含一个数据结构(用于存放各种类型的数据)以及一个指针,该指针一般称为next,用来指向下一个结点的位置。由于下一个结点也是链表类型,所以next的指针也要定义为链表类型。

链表初始化

linklist *  List_init()
{
    linklist *HeadNode= (linklist*)malloc(sizeof(linklist));
    if(HeadNode == NULL)
    {
        printf("空间缓存不足");
        return HeadNode;
    }
    HeadNode->Element= 0;
    HeadNode->next= NULL;
    returnHeadNode;
}

链表初始化的作用就是生成一个链表的头指针,以便后续的函数调用操作。在没有任何输入的情况下,我们首先需要定义一个头指针用来保存即将创建的链表。所以函数实现过程中需要在函数内定义并且申请一个结点的空间,并且在函数的结尾将这个结点作为新建链表的头指针返回给主调函数。

链表的创建

void CreatList(linklist *HeadNode,int *InData,int DataNum)
{
    int i = 0;
    linklist *CurrentNode = (linklist*) HeadNode;
    for(i = 0;i<DataNum;i++)
    {
        CurrentNode->Element = InData[i];
        if(i< DataNum-1)// 由于每次赋值后需要新建结点,为了保证没有多余的废结点
        {
            CurrentNode->next =(linklist *)malloc(sizeof(linklist));
            CurrentNode= CurrentNode->next;
        }
    }
    CurrentNode->next= NULL;
}

程序内先新建了一个指针变量CurrentNode用来表示当前的结点指针。最初,我们让CurrentNode指向了首元结点HeadNode的位置。然后根据输入数组的大小进行循环赋值,赋值完成之后再重新申请一个结点空间用来存放下一个结点的内容,并且将当前结点指针CurrentNode指向新生成的结点。由于链表创建函数调用时已经存在一个首元结点,按照这个逻辑最终在使用最后一个数组数据赋值之后还会多生成一个结点。因此,为了保证没有冗余的结点,循环内需要用DataNum-1来控制结点数量。

插入结点

bool InsertList(linklist *HeadNode,int LocateIndex,int InData)
{
    int i=1;// 由于起始结点HeadNode是头结点,所以计数从1开始
    linklist *CurrentNode= (linklist *) HeadNode;  //将CurrentNode指向待插入位置的前一个结点(index -1)
    while(CurrentNode&& i<LocateIndex-1)
    {
        CurrentNode= CurrentNode->next;
        i++;
    }
    linklist *NodeToInsert=(linklist*)malloc(sizeof(linklist));
    if(NodeToInsert == NULL)
    {
        printf("空间缓存不足");
        return ERROR;
    }
    NodeToInsert->Element= InData;
    NodeToInsert->next = CurrentNode->next;
    CurrentNode->next = NodeToInsert;
    return OK;
}

需要在指定位置之后(比如A2结点)插入一个新结点时。首先我们需要新建立一个结点NodeToInsert,然后将新结点的next指向A3,并且将A2的next指针指向新建立的结点NodeToInsert,切记操作顺序不要改变。如果操作顺序变换一下,先将A2的next指向了新建立的结点,那么我们就丢失了A3的寻址方式。因此,在将A2的next指向其他任何地方之前,请务必将A3的地址存在NodeToInsert或者某个新建节点内。

删除节点

bool DeleteList(linklist * HeadNode,int index, int * DataToDel)
{
    int i = 1;
    linklist *CurrentNode  = HeadNode; 
    linklist *NodeToDelete;   //将CurrentNode指向待删除位置的前一个结点(index -1)
	while(CurrentNode&& i<index-1)
    {
        CurrentNode= CurrentNode->next;
        i++;
    }
    NodeToDelete = CurrentNode->next;
    *DataToDel =NodeToDelete->Element;
    CurrentNode->next= NodeToDelete->next;
    free(NodeToDelete);
    return OK;
}

新建的链表类型的指针NodeToDelete是为了释放CurrentNode->next。直接使用CurrentNode ->next = CurrentNode ->next->next只是将该节点从链表中剔除,但是没有将其空间从内存中释放。而且,经过了CurrentNode ->next = CurrentNode ->next->next这个赋值语句之后,我们已经丢失了原本需要删除的结点的地址。所以,在删除之前新建了个结点用来保存待删除的结点地址,以便后面对内存空间的释放。

查找链表数据

int LocateElement(linklist * HeadNode,int DataToLocate)
{
    int LocateIndex = 1;
    linklist *CurrentNode= (linklist*) HeadNode;
    while(CurrentNode)
    {
        if(CurrentNode->Element== DataToLocate)
        {
            returnLocateIndex; //找到位置返回
        }
        CurrentNode= CurrentNode->next;
        LocateIndex++;
    }
    return -1; //如果没有这个值,返回-1
}

我的代码练习

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

//define linklist
typedef struct linklist {
    int data ;
    struct linklist *next;
}linklist;

linklist *headlinklist;
//init linklist
linklist* init_linklist()
{
    linklist *headlinklist = (linklist*)malloc(sizeof(linklist));
    if(headlinklist==NULL)
    {
        printf("no enough room");
        return headlinklist;
    }
    headlinklist ->data = 0;
    headlinklist ->next = NULL;
    return headlinklist;
}

//create linklist
void creatlinklist()
{
    int a[10],i;
    for(i=0;i<10;i++)
        a[i]=i+1;
    linklist *currentlinklist = (linklist*)headlinklist;
    for(i=0;i<10;i++)
    {
        currentlinklist ->data = a[i];
        if(i<9)
        {
            currentlinklist ->next = (linklist*)malloc(sizeof(linklist));
            currentlinklist = currentlinklist ->next;
        }
    }
    currentlinklist ->next = NULL;
}

//insert node
int insertnode(int locate_insert, int data_insert)
{
    int i;
    linklist *currentlinklist = headlinklist;
    for(i = 0; i < locate_insert - 1; i++)
    {
        currentlinklist = currentlinklist->next;
    }
    linklist *newnode = (linklist*)malloc(sizeof(linklist));
    newnode ->data = data_insert;
    newnode ->next = currentlinklist->next;
    currentlinklist->next = newnode;
    return 0;
}

//delete node
void deletenode(int locate_delete)
{
	if(locate_delete == 1) {
		linklist *delnode = headlinklist;
		headlinklist = headlinklist->next;
		free(delnode);
		return;
	} else if(locate_delete > 1){
		int i;
		linklist *currentlinklist = headlinklist;
		for(i=0;i<locate_delete - 1;i++)
		{
			currentlinklist = currentlinklist->next;
		}
		linklist *delnode = currentlinklist ->next;
		currentlinklist ->next = delnode ->next;
		free(delnode);
	} else {
        printf("wrong parameter\n");
    }
    return;
}

//find node
int findnode(int data_find)
{
    int i=0;
    linklist *currentlinklist = headlinklist;
    while(currentlinklist->data != data_find && currentlinklist->next != NULL)
    {
        currentlinklist = currentlinklist ->next;
        i++;
    }
    return i+1;
}

int main()
{
    int i;
    headlinklist = init_linklist();
    creatlinklist();
    linklist *currentlinklist = headlinklist;
    printf("The new linklist is: \n");
    while(currentlinklist->next != NULL)
    {
        printf("%d  ",currentlinklist->data);
        currentlinklist = currentlinklist ->next;
    }
    printf("\n");
    insertnode(3,10);
    currentlinklist = headlinklist;
    printf("The linklist after insert is: \n");
    while(currentlinklist->next != NULL)
    {
        printf("%d  ",currentlinklist->data);
        currentlinklist = currentlinklist ->next;
    }
    printf("\n");
    deletenode(1);
    currentlinklist = headlinklist;
    printf("The linklist after delete is: \n");
    while(currentlinklist->next != NULL)
    {
        printf("%d  ",currentlinklist->data);
        currentlinklist = currentlinklist ->next;
    }
    printf("\n");
    i = findnode(8);
    printf("The number '8' is located at %d node\n",i);
    return 0;
}

运行结果

在这里插入图片描述

双向链表

我的代码练习

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

//define doublelinklist
typedef struct doublelink {
    int data;
    struct doublelink *prior;
    struct doublelink *next;
}doublelink;

doublelink *headnode;
//init doublelinklist
doublelink* init_list()
{
    doublelink *headnode = (doublelink*)malloc(sizeof(doublelink));
    if(headnode == NULL)
    {
        printf("no enough room");
        return headnode;
    }
    headnode ->data = 0;
    headnode ->next = headnode;
    headnode ->prior = headnode;
    return headnode;
}

//create doublelinklist
void create_list()
{
    int a[10],i;
    for(i=0;i<10;i++)
        a[i]=i;
    doublelink *currentnode = headnode;
    for(i=0;i<10;i++)
    {
        currentnode ->data = a[i];
        if(i<9)
        {
            currentnode ->next = (doublelink*)malloc(sizeof(doublelink));
            currentnode = currentnode ->next;
        }
    }
    currentnode ->next = headnode;
}

//insert node
int insert_node(int locate_insert, int data_insert)
{
    int i;
    doublelink *currentnode = (doublelink*)headnode;
    for(i=0;i<locate_insert-1;i++)
    {
        currentnode ->prior = currentnode;
        currentnode = currentnode->next;
    }
    doublelink *newnode = (doublelink*)malloc(sizeof(doublelink));
    newnode ->data = data_insert;
    newnode ->next = currentnode ->next;
    newnode ->prior = currentnode;
    currentnode ->next = newnode;
    return 0;
}

//delete node
void delete_node(int locate_delete)
{
    int i;
    doublelink *deleteNode = headnode;
    if(locate_delete == 1) {
        headnode->prior->next = headnode->next;
        headnode->next->prior = headnode->prior;
        headnode = headnode->next;
        free(deleteNode);
    } else if(locate_delete > 1) {
        for(i = 0; i < locate_delete; i++) {
            deleteNode = deleteNode->next;
        }
        deleteNode->prior->next = deleteNode->next;
        deleteNode->next->prior = deleteNode->prior;
        free(deleteNode);
    } else {
        printf("wrong parameter\n");
    }
}

//find node
int find_node(int data_find)
{
    int i=0;
    doublelink *currentnode = headnode;
    while(currentnode->data != data_find && currentnode->next != NULL)
    {
        currentnode = currentnode ->next;
        i++;
    }
    return i+1;
}

int main()
{
    int i;
    headnode = init_list();
    create_list();
    doublelink *currentnode = headnode;
    printf("The new doublelink is: \n");
    while(currentnode->next != headnode)
    {
        printf("%d  ",currentnode->data);
        currentnode = currentnode ->next;
    }
    printf("\n");
    insert_node(3,10);
    currentnode = headnode;
    printf("The doublelink after insert is: \n");
    while(currentnode->next != headnode)
    {
        printf("%d  ",currentnode->data);
        currentnode = currentnode ->next;
    }
    printf("\n");
    delete_node(1);
    currentnode = headnode;
    printf("The doublelink after delete is: \n");
    while(currentnode->next != headnode)
    {
        printf("%d  ",currentnode->data);
        currentnode = currentnode ->next;
    }
    printf("\n");
    i = find_node(8);
    printf("The number '8' is located at %d node\n",i);
    return 0;
}

运行结果

在这里插入图片描述

来自2022-01-14的回顾

原来我以前写的那么垃圾,全是错误。遍历链表我为啥把前后一起移动啊喂,还有为什么删除结点我也要申请内存空间啊喂,为什么完全没考虑到头结点的删除啊喂。以前真的是蠢死了。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值