本博客为本博主的浅见,有错误之处,烦请指正。
几个名词
- 数据域:我们把存储数据元素信息的域称为数据域。
- 指针域:我们把存储直接后继位置的域称为指针域。
- 结点:我们把数据域和指针域这两部分信息组成数据元素a的存储映像,称为结点(Node)。
结点代码如下:
typedef struct Node //节点(用结构体构建)
{
int data; //数据域
struct Node *pNext; //指针域
}NODE; //NODE 等价于struct Node
- 单链表:链表的每个结点中只包含一个指针域,称为单链表。
- 头指针:链表中第一个结点的存储位置,称为头指针。
- 头结点:单链表的第一个结点前附设一个结点,称为头结点。
头插法创建链表
单链表整表创建的思路:
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;
}