【数据结构学习】单链表的创建、尾插元素、指定位置插入元素、获取指定位置元素

单链表

链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。

“结点的序列”表示线性表称作线性链表(单链表),单链表是链式存取的结构。

链接存储方法

链接方式存储的线性表简称为链表(Linked List)。

链表的具体存储表示为:

① 用一组任意的存储单元来存放线性表的结点(这组存储单元既可以是连续的,也可以是不连续的)

② 链表中结点的逻辑次序和物理次序不一定相同。为了能正确表示结点间的逻辑关系,在存储每个结点值的同时,还必须存储指示其后继结点的地址(或位置)信息(称为指针(pointer)或链(link))

链式存储是最常用的存储方式之一,它不仅可用来表示线性表,而且可用来表示各种非线性的数据结构。

结点结构

data域--存放结点值的数据域

next域--存放结点的直接后继的地址(位置)的指针域(链域)

链表通过每个结点的链域将线性表的n个结点按其逻辑顺序链接在一起的,每个结点只有一个链域的链表称为单链表(Single Linked List)

头指针head和终端结点

单链表中每个结点的存储地址是存放在其前趋结点next域中,而开始结点无前趋,故应设头指针head指向开始结点。链表由头指针唯一确定,单链表可以用头指针的名字来命名。

终端结点无后继,故终端结点的指针域为空,即NULL。

上代码

头文件定义

#ifndef __FY_LINKLIST_H
#define __FY_LINKLIST_H

//数据类型定义
typedef int data_t;

//结点结构体定义
typedef struct node{
    data_t data;
    struct node *next;
}listnode,*linklist;

//创建一个表
linklist list_creat(void);
//表尾插入一个元素
int list_tail_insert(linklist H,data_t data);
//获取表中某个结点
listnode* list_get(linklist H,int pos);
//在指定位置插入一个元素
int list_insert(linklist H,data_t data,int post);
//遍历表
int list_show(linklist H);

#endif

 C文件

#include "linklist.h"
#include "stdio.h"
#include "stdlib.h"

//创建一个结点
listnode *creatNode(data_t data){
    listnode *newnode = (listnode *)malloc(sizeof(listnode));
    if(newnode==NULL){
        printf("创建结点失败!\n");
        return NULL;
    }
    newnode->data = data;
    newnode->next = NULL;
    return newnode;
}

//创建一个表
linklist list_creat(void){
    linklist H = (linklist)malloc(sizeof(listnode));
    if(H==NULL){
        printf("创建链表失败!\n");
        return NULL;
    }
    H->data = 0;
    H->next = NULL;
    return H;
}

//表尾插入一个元素
int list_tail_insert(linklist H,data_t data){
    if(H == NULL) {
        printf("链表不存在!\n");
        return -1;
    }
    listnode *newnode = creatNode(data);
    if(newnode == NULL) return -1;
    listnode *p = H;

    while(p->next != NULL){
        p = p->next;
    }
    p->next = newnode;
    return 0;
}

//获取表中某个结点的地址
/*
定义:
头结点的位置是-1
结点的位置是从0开始的,
*/
listnode * list_get(linklist H,int pos){
    int i;
    listnode *p;
    //防御性编程
    if(H==NULL){
        printf("链表不存在!\n");
        return NULL;
    }
    if(pos<-1) {
        printf("获取节点失败,位置无效!\n");
        return NULL;
    }
    if(H->next == NULL){
        printf("获取结点失败,链表为空!\n");
    }

    p = H;//指向头结点,位置为-1
    for(i=-1;i<pos;i++){
        if(p->next == NULL){
            printf("获取结点失败,结点位置不存在!\n");
            return NULL;
        }
        p = p->next;
    }
    return p;
}

//在指定位置插入一个元素
int list_insert(linklist H,data_t data,int post){
    if(H==NULL){
        printf("插入结点失败,链表不存在!\n");
        return -1;
    }
    //获取结点位置的上一个结点
    listnode *lastnode = list_get(H,post-1);
    if(lastnode == NULL) {
        printf("插入结点失败,位置不合法!\n");
        return -1;
    }
    //为该元素创建一个结点
    listnode *newnode = creatNode(data);
    newnode->next = lastnode->next;
    lastnode->next = newnode;
    return 0;
}

//遍历表
int list_show(linklist H){
    if(H == NULL){
        printf("遍历链表失败,链表不存在!\n");
        return -1;
    }
    listnode *p = H;
    while(p->next !=NULL){
        p = p->next;
        printf("%d ",p->data);
    }printf("\n");
    return 0;
}

测试的main文件

#include "stdio.h"
#include "stdlib.h"
#include "linklist.h"


int main(void){
	data_t value;
    //创建一个空链表
    linklist H = list_creat();

	//初始化插入几个数据
    list_tail_insert(H,1);
    list_tail_insert(H,3);
    list_tail_insert(H,5);
    list_tail_insert(H,7);
	printf("初始链表数据为:\n");
	list_show(H);
	printf("\n***********尾插法插入元素测试***********\n");
	while(1){
		printf("请输入一个数据,输入-1为结束测试!\n");
		scanf("%d",&value);
		if(value == -1) break;
		list_tail_insert(H,value);
		printf("插入新数据后的链表元素为:\n");
		list_show(H);
	}
	printf("\n***********查找指定位置元素测试**********\n");
	while(1){
		printf("请输入一个位置,输入-1为结束测试!\n");
		scanf("%d",&value);
		if(value == -1) break;
		listnode *p = list_get(H,value);
		if(p!=NULL){
			printf("该位置的元素数据为:%d\n",p->data);
		}
	}
	printf("\n***********指定位置插入元素测试**********\n");
	while(1){
		int pos;
		data_t data;
		int res;
		printf("请输入要插入的位置及要插入的数据:如2 3代表在第二个位置插入数据3\n输入-1 -1为结束测试!\n");
		scanf("%d %d",&pos,&data);
		if(pos == -1 && data == -1) break;
		res = list_insert(H,data,pos);
		if(res == 0){
			printf("在指定位置插入元素成功,插入后的链表为:\n");
			list_show(H);
		}
	}
    list_show(H);

    return 0;
}

 测试运行结果如下:

By Urien 2021年2月2日 23:03:57

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值