如何用C语言创建链表
链表使线性表的一种,比起顺序表,链表可以根据需要改变自身的大小,动态分配内存,比循序表更灵活。这里介绍我用c语言实现链表基本操作的方法。
#include<stdio.h>
#include<malloc.h>//调用malloc
#pragma warning(disable:4996) //防止scanf(),printf报错
定义一个结构体,用来储存链表的节点:
typedef struct node {
int data = 0;
node* next = NULL;
}Node, * PNode;
定义一个结构体,存放指向表头和表尾的指针,同时用于记录链表的长度:
typedef struct linkedlist {
PNode head = NULL;
PNode tail = NULL;
int length = 0;
}Llist;
定义函数,用于实现以下功能
Llist init_list(); //创建一个链表
Llist append_list(Llist llist); //在链表最后插入一个结点
Llist ins_node(Llist llist); //在链表指定位置中插入一个结点
Llist del_node(Llist llist); //删除链表指定位置处的一个节点
void print_list(Llist llist); //打印整段链表
创建链表的过程中,思路是这样的:先malloc一块内存,令head指针和tail指针都指向这块内存空间,再令这块内存的next指向NULL,输入第一个值,完成第一个结点的创建。若表长大于1,则不断调用appen_list()函数,增长链表的长度。实现如下:
Llist init_list() {
Llist llist;
int length;
//Create list head
llist.head = llist.tail=(PNode)malloc(sizeof(Node));
printf("Enter the length :");
scanf("%d", &length);
printf("Enter the 1 node:");
scanf("%d", &llist.head->data);
llist.length++;
llist.head->next = NULL;
//append other node
for (; llist.length < length;)
llist = append_list(llist);//函数实现见下放
return llist;
}
append_list()函数实现过程如下:
Llist append_list(Llist llist) {
PNode node = (PNode)malloc(sizeof(Node));//申请一块新内存
printf("Enter the %d node:", llist.length + 1);
scanf("%d", &node->data);
node->next = NULL; //因为在尾部,使新内存的next指向NULL
llist.tail->next = node;//令原链表的尾结点指向新申请出来的结点
llist.tail = node; //尾节点指向新申请的结点
llist.length++; //表长度加一
return llist;
}
创建完一段链表后,我们写一个print_list函数将他打印出来:
void print_list(Llist llist) {
PNode pos;//定义position,从头结点开始遍历所有结点
printf("**************************************************\n");
for (pos = llist.head; pos; pos = pos->next)
printf("%d\t",pos->data);
printf("\n**************************************************\n");
}
删除结点的函数实现:
Llist del_node(Llist llist) {
int Dpos;//输入删除的位置,存在Dpos处
PNode pos1 = (PNode)malloc(sizeof(Node));
pos1 = llist.head;//结点pos1,令其等于头结点
PNode pos2 = pos1->next;//结点pos2指向pos1后面的位置
printf("Enter the delete position:");
scanf("%d", &Dpos);、
if(!(Dpos <= llist.length)) //若位置不小于表长,报错
printf("position false");
//若要删除第一个结点(头节点),令头节点指向其下一个位置,在free掉原来第一个结点
if (Dpos == 1) {
llist.head = llist.head->next;
free(pos1);
pos1 = llist.head;
}
//删除其他结点,需要遍历链表,并设置一个计数器,记录pos1和pos2移动了多少位置
else {
for (int cnt = 1; cnt < Dpos - 1; cnt++) {
pos1 = pos1->next;
pos2 = pos1->next;
}
//当pos2指向要删除的位置时,令pos1指向pos2后面的位置,再free掉pos2,便把该结点删除了
pos1->next = pos2->next;
free(pos2);
}
llist.length--;//删除一个结点,表长减一
return llist;
}
插入结点的实现:
Llist ins_node(Llist llist) {
int Ipos;
PNode pos = llist.head; //用于遍历链表,找到插入位置
PNode node = (PNode)malloc(sizeof(Node)); //新的结点
printf("Enter the insert position:");
scanf("%d", &Ipos);
if (!(Ipos <= llist.length)) //若插入位置不小于表长,报错
printf("position false!\n");
printf("Enter the value:");
scanf("%d", &node->data);
if (Ipos == 1) { //若在第一个位置插入结点
node->next = llist.head; //令新结点指向原表头
llist.head= node; //再让新结点成为表头
}
else {
for (int cnt = 1; cnt < Ipos - 1; cnt++)//遍历链表,直到要插入的位置
pos = pos->next;
node->next = pos->next; //令新结点指向当前结点的后一个结点
pos->next = node; //再令当前结点指向新结点
}
llist.length++; //表长增长
return llist;
}
用main()函数过一遍前面的函数
int main()
{
Llist llist = init_list(); //initialization a linked list
llist = del_node(llist); //delete a listnode
print_list(llist);
llist = ins_node(llist); //insert a listnode
print_list(llist);
printf("the length of list:%d\n", llist.length);
return 0;
}
得到结果: