C语言数据结构之链表
首先呢,开始数据结构中的第一个部分-----线性表
首先我们想到的问题一定是定义一个结构体变量:
//定义链表
typedef struct Node
{
int data;
struct Node* next;
}Node;
定义好了一个结构体变量,接下来呢,一个链表得有个头,对吧:
//创建头节点
Node* CreatHeadNode()
{
Node* headNode = (Node*)malloc(sizeof(Node));
headNode->next = NULL;
return headNode;
}
接下来呢,定义一个函数来产生一个新节点:
//创建一个节点
Node* CreatNode(int data)
{
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = data;
newNode->next = NULL;
return newNode;
}
接下来呢,当然要考虑怎样连接这些节点呢,有两种方法供我们选择:
1.头插法
//将链表连接(头插法)
Node* ConnectNodebyhead(Node* headNode, int data)
{
Node* NewNode = CreatNode(data);
NewNode->next = headNode->next;
headNode->next = NewNode;
return headNode;
}
即相当于先把NewNode的next与headNode->next连接,再把head->next与NewNode相连即可。
2.尾插法
//将链表连接(尾插法)
void ConnectNodebytail(Node* headNode, int data)
{
Node* NewNode = CreatNode(data);
NewNode->next = headNode->next;
headNode->next = NewNode;
headNode = NewNode;
}
其实可以将尾接法看作头接法在最后将headNode移动到NewNode的位置,这样可以保证一个链表的顺序是正向的(可以在后面的测试样例中看出)。
然后呢,我们就应该考虑一个链表具有哪些功能呢?
1.插入
//插入
Node* InSertNode(int data, int i,Node* headNode)
{
int j;
j = 1;
Node* insertNode = CreatNode(data); //要插入的节点
while ((headNode->data) & (j < i))
{
headNode = headNode->next;
j++;
}
if (!headNode || j > i)
{
printf("不存在该节点");
exit(0);
}
insertNode->next = headNode->next;
headNode->next = insertNode;
return headNode;
}
2.删除
//删除
Node* DeleteNode(int i,Node* headNode)
{
int j;
j = 1;
Node* ConnectNode = CreatNode(NULL); //起过渡的作用
while (headNode->data & j < i)
{
headNode = headNode->next;
j++;
}
if (!headNode || j > i)
{
printf("不存在该节点");
exit(0);
}
ConnectNode = headNode->next;
headNode->next = ConnectNode->next;
free(ConnectNode);
return headNode;
}
3.取出某位元素
//取出元素
void Take_outNode(Node* headNode, int i)
{
int j = 0;
while (headNode && j < i)
{
headNode = headNode->next;
j++;
}
if (!headNode || j > i)
{
printf("该节点不存在");
exit(0);
}
printf("第%d个元素为%d\n", i, headNode->data);
}
4.反转链表
//反转
Node* Flip_Node(Node* headNode)
{
Node* pr = (Node*)malloc(sizeof(Node));
pr = NULL;
Node* cur = (Node*)malloc(sizeof(Node));
cur = headNode->next;
while (cur)
{
Node* temp = (Node*)malloc(sizeof(Node));
temp = cur->next;
cur->next = pr;
pr = cur;
cur = temp;
}
printf("%d\t", pr->data);
return pr;
}
5.链表长度
//链表长度
int Length(Node* headNode)
{
int i = 0;
while (headNode)
{
headNode = headNode->next;
i++;
}
return i-1;
}
6.清空链表
//清空链表
void Clear_Node(Node* headNode)
{
Node* Node_clear = (Node*)malloc(sizeof(Node));
Node_clear = headNode;
if (Node_clear == NULL)
{
printf("链表不存在");
exit(0);
}
while (headNode)
{
headNode = headNode->next;
free(Node_clear);
Node_clear = headNode;
}
free(Node_clear);
}
接下来呢,我们想要检验我们做的对不对呢,是不是可以封装一个函数来打印链表呢
//打印链表(方便检验)
void PrintList(Node* headNode)
{
Node* Node_p = headNode->next; //Node_p为头节点的下一个结构体变量
while (Node_p)
{
printf("%d\t", Node_p->data);
Node_p = Node_p->next;
}
printf("\n");
}
下面呢,就来看看整体的代码吧
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//定义链表
typedef struct Node
{
int data;
struct Node* next;
}Node;
//创建头节点
Node* CreatHeadNode()
{
Node* headNode = (Node*)malloc(sizeof(Node));
headNode->next = NULL;
return headNode;
}
//创建一个节点
Node* CreatNode(int data)
{
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = data;
newNode->next = NULL;
return newNode;
}
//将链表连接(头插法)
void ConnectNodebyhead(Node* headNode, int data)
{
Node* NewNode = CreatNode(data);
NewNode->next = headNode->next;
headNode->next = NewNode;
}
//将链表连接(尾插法)
void ConnectNodebytail(Node* headNode, int data)
{
Node* NewNode = CreatNode(data);
NewNode->next = headNode->next;
headNode->next = NewNode;
headNode = NewNode;
}
//插入
Node* InSertNode(int data, int i,Node* headNode)
{
int j;
j = 1;
Node* insertNode = CreatNode(data); //要插入的节点
while ((headNode->data) & (j < i))
{
headNode = headNode->next;
j++;
}
if (!headNode || j > i)
{
printf("不存在该节点");
exit(0);
}
insertNode->next = headNode->next;
headNode->next = insertNode;
return headNode;
}
//删除
Node* DeleteNode(int i,Node* headNode)
{
int j;
j = 1;
Node* ConnectNode = CreatNode(NULL); //起过渡的作用
while (headNode->data & j < i)
{
headNode = headNode->next;
j++;
}
if (!headNode || j > i)
{
printf("不存在该节点");
exit(0);
}
ConnectNode = headNode->next;
headNode->next = ConnectNode->next;
free(ConnectNode);
return headNode;
}
//取出元素
void Take_outNode(Node* headNode, int i)
{
int j = 0;
while (headNode && j < i)
{
headNode = headNode->next;
j++;
}
if (!headNode || j > i)
{
printf("该节点不存在");
exit(0);
}
printf("第%d个元素为%d\n", i, headNode->data);
}
//反转
Node* Flip_Node(Node* headNode)
{
Node* pr = (Node*)malloc(sizeof(Node));
pr = NULL;
Node* cur = (Node*)malloc(sizeof(Node));
cur = headNode->next;
while (cur)
{
Node* temp = (Node*)malloc(sizeof(Node));
temp = cur->next;
cur->next = pr;
pr = cur;
cur = temp;
}
printf("%d\t", pr->data);
return pr;
}
//链表长度
int Length(Node* headNode)
{
int i = 0;
while (headNode)
{
headNode = headNode->next;
i++;
}
return i-1;
}
//清空链表
void Clear_Node(Node* headNode)
{
Node* Node_clear = (Node*)malloc(sizeof(Node));
Node_clear = headNode;
if (Node_clear == NULL)
{
printf("链表不存在");
exit(0);
}
while (headNode)
{
headNode = headNode->next;
free(Node_clear);
Node_clear = headNode;
}
free(Node_clear);
}
//打印链表(方便检验)
void PrintList(Node* headNode)
{
Node* Node_p = headNode->next; //Node_p为头节点的下一个结构体变量
while (Node_p)
{
printf("%d\t", Node_p->data);
Node_p = Node_p->next;
}
printf("\n");
}
int main()
{
int a[10] = { 0 };
srand(time(NULL));
printf("原数值:\n");
for (int i = 0;i < 10;i++)
{
a[i] = rand() % 100;
printf("%d\t", a[i]);
}
printf("\n");
Node* headNode_head = CreatHeadNode();
printf("使用头插法:\n");
for (int i = 0;i < 10;i++)
{
ConnectNodebyhead(headNode_head, a[i]);
}
PrintList(headNode_head);
Node* headNode_tail = CreatHeadNode();
printf("使用尾插法:\n");
for (int i = 0;i < 10;i++)
{
ConnectNodebytail(headNode_tail, a[i]);
printf("%d\t", headNode_tail->next->data);
}
printf("\n以头插法为例,在第2个位置插入5:\n");
InSertNode(5, 2, headNode_head);
PrintList(headNode_head);
printf("以头插法为例,删除第二个位置的元素: \n");
DeleteNode(2, headNode_head);
PrintList(headNode_head);
Take_outNode(headNode_head, 2); //取出第二个元素
printf("该链表长度为%d\n", Length(headNode_head));
printf("翻转后链表:\n");
PrintList(Flip_Node(headNode_head));
Clear_Node(headNode_head);
printf("清空链表后的第一个元素:\n%d\n", headNode_head->data);
system("pause");
return 0;
}
最后呢,我们来检验一下吧
大功告成!!
作为自己的第一篇文章,如果有什么问题请指正,谢谢。