细说线性表的链式存储结构——链表

本博客为本博主的浅见,有错误之处,烦请指正。

几个名词

  1. 数据域:我们把存储数据元素信息的域称为数据域。
  2. 指针域:我们把存储直接后继位置的域称为指针域。
  3. 结点:我们把数据域和指针域这两部分信息组成数据元素a的存储映像,称为结点(Node)。
    结点
    结点代码如下:
typedef struct Node  //节点(用结构体构建)
{
 int data; //数据域
 struct Node *pNext;  //指针域
}NODE;  //NODE 等价于struct Node
  1. 单链表:链表的每个结点中只包含一个指针域,称为单链表。
  2. 头指针:链表中第一个结点的存储位置,称为头指针。
  3. 头结点:单链表的第一个结点前附设一个结点,称为头结点。
    头结点及头指针

头插法创建链表

单链表整表创建的思路:
1.声明一个len长度来存放有效结点的个数和val来存放用户输入的节点的值;
2.创建一个不存放有效数据的头结点pHead;
3.循环:1)生成新结点赋值给pNew;2)输入值赋值给pNew->data;3)将pNew插入头结点和前一新结点之间。

头插法创建单链表
Node * create_list()
{
    int len;	//用来存放有效结点的个数
    int val;	//用来存放用户输入的节点的值
    NODE *pHead = (NODE *)malloc(sizeof(NODE));	//动态分配一个不存放有效数据的头结点
    if(pHead == NULL)	//增强代码健壮性
    {
        pritf("分配失败,程序终止!\n");
        exit(-1);
    }
        printf("请输入您要生成的链表节点的个数:len = ");
    scanf("%d", &len);
    for (int i = 0; i < len; i++)
    {
        printf("请输入第%d个节点的值:", i + 1);
        scanf("%d", &val);
        //创建新结点
        NODE *pNew = (NODE *)malloc(sizeof(NODE));
        if (pNew == NULL)
        {
            printf("分配失败,程序终止!\n");
            exit(-1);
        }
        else
        {
            pNew->data = val;
            pNew->pNext = pHead->pNext;
            pHead->pNext = pNew;
        }
    }
    return pHead;
}

头插法创建链表

输出链表

输出链表思路:
1.声明一个工作指针p指向第一个节点;
2.当p != NULL时输出结点的值

void traverse_list(NODE *pHead)	//输出链表
{
    NODE *p = pHead->pNext;	//工作指针p指向第一个结点
    while (p != NULL)
    {
        printf("%d  ", p->data);
        p = p->pNext;
    }
    printf("\n");
}

判断链表是否为空

bool is_empty(NODE * pHead)
{
    if (pHead->pNext == NULL)
        return true;
    else
        return false;
}

查看链表长度

int length_list(NODE * pHead)
{
    NODE *p = pHead->pNext;	//工作指针,原理如上
    int length = 0;
    while (p != NULL)
    {
        length++;
        p = p->pNext;
    }
    return length;
}

指定位置插入结点

在pHead所指向的链表的第pos个结点插入一个新结点,新结点的值为val

bool insert_list(NODE *pHead, int pos, int val)
{
 int i = 0;
 NODE * p = pHead;
 while (p != NULL && i < pos - 1)
 {
  p = p->pNext;
  i++;
 }
 if (i > pos - 1 || p == NULL)
  return false;
 Node * pNew = (NODE *)malloc(sizeof(NODE));
 if (pNew == NULL)
 {
  printf("动态分配内存失败!\n");
  exit(-1);
 }
 pNew->data = val;
 pNew->pNext = p->pNext;
 p->pNext = pNew;
 return true;
}

指定位置删除节点

在pHead所指向的链表的第pos个结点处删除后面的结点

bool delete_list(NODE * pHead, int pos, int *pVal)
{
 int i = 0;
 NODE * p = pHead;
 while (p != NULL && i < pos - 1)
 {
  p = p->pNext;
  i++;
 }
 if (i > pos - 1 || p->pNext == NULL)
  return false;
 NODE *q = p->pNext;
 *pVal = q->data;
 //删除p结点后面的结点
 p->pNext = p->pNext->pNext;
 free(q);
 q == NULL;
 return true;
}

排序

难难难!!!

void sort_list(NODE *pHead)
{
 int i, j, temp;
 NODE * p, *q;
 for (i = 0, p = pHead->pNext; i < length_list(pHead) - 1; i++, p = p->pNext)
  for (j = i + 1, q = p->pNext; j < length_list(pHead); j++, q = q->pNext)
  {
   if (p->data > q->data)
   {
    temp = p->data;
    p->data = q->data;
    q->data = temp;
   }
  }
}

加上头文件、函数声明、main函数

//头文件
#include <stdio.h>
#include <stdlib.h>
//结点结构体
typedef struct Node
{
    int data;
    struct Node *pNext;
}NODE;
//函数声明
NODE * create_list();
void traverse_list(NODE * pHead);  //输出链表
bool is_empty(NODE * pHead);  //判断链表是否为空
int length_list(NODE * pHead);  //链表长度
bool insert_list(NODE * pHead, int pos, int val);
bool delete_list(NODE * pHead, int pos, int *pVal);
void sort_list(NODE * pHead);
int main()
{
    NODE *pHead = NULL;
    int length = 0,val = 0;
    pHead = create_list(); //create_list()功能:创建一个非循环单链表,并将该链表的头结点的地址赋给pHead
    printf("链表数据域值为:\n");
    traverse_list(pHead);  //遍历输出链表
    
    if (is_empty(pHead))
	printf("链表为空!\n");
    else
        printf("链表不为空!\n");	
    
    length = length_list(pHead);
    printf("链表长度为:%d\n", length);

    sort_list(pHead);
    printf("链表排序后:\n");
    traverse_list(pHead);
    
    insert_list(pHead, 4, 33);
    printf("插入之后的链表:\n");
    traverse_list(pHead);
    
    if (delete_list(pHead, 4, &val))
        printf("删除成功,您删除的元素是:%d\n", val);
    else
        printf("删除失败,您删除的元素不存在!\n");
    printf("删除后的链表为:\n");
    traverse_list(pHead);
   
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值