对于链表,我们可以知道他和算法会有相关。我们至少通过两组结构来存储:数组和链表。
接下来,我们来进行单链表的实现
在这里,我们可以进行增加,删除,求长度,排序。
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
//定义了一个链表节点的数据类型
//在这里你要清楚什么事头结点,头指针,首节点,尾节点
//头节点的数据类型和首结点的是一模一样的。
//头节点是首节点前面的那个节点,头节点并不存放有效数据,
//头节点的就是为了方便链表的操作。
//确定一个链表只需 要知道头指针,
//链表最后的尾节点为空
//判断尾节点,只需要判断尾节点的指针域为空。
//
typedef struct Node
{
int data;//数据域
struct Node *pNext;
//指针域,这个指针域指向下一个结点,类型必须和结构体类型一样,
//所以才是struct Node类型
//其实说白了就是递归,next存放的是地址,
}NODE, *PNODE;//要记住这里的的类型要加上struct Node 类型
//在这里NODE就是等价于struct Node ,PNODE等价于struct Node *
PNODE create_list()
{
int len;//存放有效节点个数
int i;
int val;//存放用户输入节点的值
//首先分配一个不存放有效数据的头结点
PNODE pHead = (PNODE)malloc(sizeof(NODE));
//
//接下来判断malloc是否动态开辟成功
if (NULL == pHead)
{
printf("动态开辟失败!\n");
exit(1);//用来终止程序。
//exit()函数一般是返回给操作系统的,
//当函数里面的参数为非0时,程序终止,当参数为0时,函数继续。
}
PNODE pTail = pHead;//这里是对尾节点的创建;
pTail->pNext = NULL;
printf("输入你需要生成链表节点个数:");
scanf("%d",&len);
for (i = 0; i < len; i++)
{
printf("请输入第%d个节点的值:",i+1);
scanf("%d", &val);
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if (NULL == pNew)
{
printf("动态开辟失败!\n");
exit(1);
}
pNew->data = val;//在这里面对每一个节点进行赋值。
pTail->pNext = pNew;//在这里把pNew放到尾节点的指针域里面去。
pNew->pNext = NULL;//这里把新创建的节点变成尾节点。
pTail = pNew;//把新创建的看作头指针。
}
return pHead;//返回头指针。方便后续操作
}
//遍历链表程序。
void traverse_list(PNODE pHead)
{
//在这注意不能像数组一样对下标进行操作。因为链表是不连续的。
//所以在这里进行指针操作。
PNODE p=pHead->pNext;//首先的操作是将头指针域赋给一个指针变量
while (NULL != p)//在这里如果p中不为空,则就向下一个进行移动
{
printf("%d ", p->data);
p = p->pNext;//当这里p为所指向的指针域为倒数第二个时,这时存放
//的就是最后一个的地址,所以这是再进行一次循环,然后当p再移动的时候
//这时p就为null了,退出循环。
}
printf("\n");
}
int is_empty(PNODE pHead)
{
if (NULL == pHead->pNext)
{
return 1;
}
return 0;
}
int lenght_list(PNODE pHead)
{
int len = 0;
PNODE p = pHead->pNext;
while (p)
{
len++;
p = p->pNext;
}
return len;
}
void soert_list(PNODE pHead)
{
int i = 0, j = 0, tmp = 0;
int len = lenght_list(pHead);
PNODE p,q;
//在这我们应该知道,只要是线性结构的,排序方法都是一样的
//所以在这你需要联想数组的排序方法。
for (i = 0,p=pHead->pNext; i < len - 1; i++,p=p->pNext)//在这里给出一个结点的data
{
for (j = i+1,q=p->pNext; j < len; j++,q=q->pNext)//在这里与这个结点之后的结点进行对比,排序。
{
if ((p->data)>(q->data))
{
tmp = p->data;
p->data = q->data;
q->data = tmp;
}
}
}
}
int insert_list(PNODE pHead, int n, int val)
{
PNODE p = pHead;
int i = 0;
//在这里进行的是寻找咱们所需要插入的那个节点
while (NULL != p&&i < n - 1)
{
p = p->pNext;
i++;
}
if (i>n - 1 || NULL == p)
{
return 0;
}
//执行完全部上面的程序以后,这里就可以说明,用户所给的参数是有效的
//接下来,我们就可以进行插入算法。
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if (NULL == pNew)
{
printf("动态开辟失败!\n");
exit(1);
}
pNew->data = val;
PNODE q = p->pNext;
p->pNext = pNew;
pNew->pNext = q;
return 1;
}
int delete_list(PNODE pHead, int n, int *pVal)
{
PNODE p = pHead;
int i = 0;
while (NULL != p->pNext && i < n - 1)
{
p = p->pNext;
i++;
}
if (i>n - 1 || NULL == p->pNext)
{
return 0;
}
PNODE q = p->pNext;
*pVal = q->data;
//输出p节点后的节点,这里要注意的是一定要记得free;
p->pNext = p->pNext->pNext;
free(q);
q = NULL;
return 1;
}
int main()
{
int len=0;
int n = 0;
int val=0;
int save = 0;
PNODE pHead = NULL;//用来存放链表头结点的地址。
pHead = create_list();
//这个函数造一个链表出来,并且返回链表的头结点的地址赋给pHead
//在这建立链表采用动态的建立链表。
//透过pHead,就可以对链表每处进行访问。
traverse_list(pHead);
//输出链表,只需要传头指针即可。
//接下来完成几个功能函数
//判断链表是否为空
if (is_empty(pHead))
{
printf("链表为空\n");
}
else
{
printf("链表不为空\n");
}
//接下来对链表求长度
printf("输出链表长度:");
len = lenght_list(pHead);
printf("%d\n",len);
//接下来完成链表的排序
printf("输出链表排序后的结果:\n");
soert_list(pHead);
traverse_list(pHead);
//接下来完成链表的插入
//在这里你要给出所要在第n个节点的前面插入一个新的节点,这个节点的数值就是val。
printf("请输入你所需要插入的节点所在的位置:");
scanf("%d", &n);
printf("请输入这个节点的值:");
scanf("%d", &val);
insert_list(pHead,n ,val);
traverse_list(pHead);
//接下来完成链表的删除
printf("请输入你所需要删除的节点所在的位置:");
scanf("%d", &n);
if (delete_list(pHead, n, &save))
{
printf("删除元素%d成功\n",save);
}
else
{
printf("删除元素%d失败\n",save);
}
traverse_list(pHead);
system("pause");
return 0;
}
测试结果
希望如果有问题,大家多多提出!