# include <stdio.h>
# include <stdlib.h>
typedef struct Linknode {
char data;
struct Linknode* next;
}*Linklist, Lnode;
// 初始化一个带头结点的链表
Linklist initlinklist() {
Linklist node = new Lnode;
node->data = '\0';
node->next = NULL;
return node;
}
// 输出函数,输出链表里的元素
void outputlinklist(Linklist L) {
Linklist p = L;
p = p->next;
printf("链表内的元素有: \n");
while (p != NULL)
{
printf("%c ", p->data);
p = p->next;
}
printf("\n");
}
// 在链表的末尾添加元素
void appendlinklist(Linklist L, char element) {
Linklist p;
p = L;
while (p->next != NULL) {
p = p->next;
}
Linklist q = new Lnode;
q->data = element;
q->next = NULL;
p->next = q;
}
// 在链表中插入元素
void insertlinklist(Linklist L, int num, char element) {
Linklist p = L;
Linklist q = new Lnode;
q->data = element;
if (num < 0) {
printf("插入位置不能是负数\n"); //判断插入位置是否为负数
return;
}
int i;
for (i = 0; i < num; i++){
p = p->next;
if (p == NULL)
{
printf("插入位置不正确\n");
return;
}
}
q->next = p->next;
p->next = q;
}
Linklist getelement(Linklist L, char element) {
Linklist p = L;
p = p->next;
while (p != NULL && p->data != element) {
p = p->next;
}
if (p->data == element)
return p;
else
printf("查抄失败,该元素不存在\n");
}
// 从链表中删除元素
void deletelinklist(Linklist L, char element) {
Linklist p = L;
while (p->next != NULL) {
if (p->next->data == element)
{
break;
}
p = p->next;
}
if (p->next == NULL)
{
printf("链表中无%c,无法删除\n",element);
return;
}
p->next = p->next->next;
}
// 测试添加,插入,删除函数
void append_insert_deletetest()
{
// step1 先建立一个有头结点的链表
Linklist testlist = initlinklist();
outputlinklist(testlist);
// step2 测试添加函数
printf("现在进行添加函数的测试\n");
printf("\n");
appendlinklist(testlist, 'H');
appendlinklist(testlist, 'e');
appendlinklist(testlist, 'l');
appendlinklist(testlist, 'l');
appendlinklist(testlist, 'o');
outputlinklist(testlist);
printf("结束添加函数测试\n");
printf("\n");
// step3 测试删除函数
printf("现在进行删除函数的测试\n");
printf("\n");
deletelinklist(testlist, 'e');
deletelinklist(testlist, 'a');
deletelinklist(testlist, 'o');
outputlinklist(testlist);
printf("结束删除函数测试\n");
printf("\n");
// step4 测试插入函数
printf("现在进行插入函数的测试\n");
printf("\n");
insertlinklist(testlist, 1, 'o');
outputlinklist(testlist);
printf("结束插入函数测试\n");
printf("\n");
}
// 地址测试
void basicAddressTest() {
Lnode tempNode1, tempNode2;
tempNode1.data = 4;
tempNode1.next = NULL;
tempNode2.data = 6;
tempNode2.next = NULL;
printf("The first node: %p, %p, %p\r\n", &tempNode1, &tempNode1.data, &tempNode1.next);
printf("The second node: %p, %p,%p\r\n", &tempNode2, &tempNode2.data, &tempNode2.next);
tempNode1.next = &tempNode2;
}
// 插入函数测试
void inserttestlist() {
Linklist p = initlinklist();
insertlinklist(p, 0, 'H');
outputlinklist(p);
insertlinklist(p, 1, 'e');
outputlinklist(p);
insertlinklist(p, 2, 'l');
outputlinklist(p);
insertlinklist(p, 3, 'l');
outputlinklist(p);
insertlinklist(p, 4, 'o');
outputlinklist(p);
insertlinklist(p, -2, 'P');
outputlinklist(p);
insertlinklist(p, 8, 'M');
outputlinklist(p);
}
int main()
{
append_insert_deletetest();
inserttestlist();
return 0;
}
插入函数图示
删除函数图示
插入函数操作:1.定义两个指针,一个用于移动到插入位置,另一个用于创建新节点接入插入位置
2.进行插入位置的判断,避免插入位置为负数
3.通过for循环,一直循环到插入位置,如果中途指针指向NULL,则说明插入位置不正确
4.如果未出现上述情况,则进行操作q->next=p->next;p->next=q;插入操作完成
删除函数操作:1.定义一个指针用于查找需要删除元素的位置
2.通过while循环,一直循环到删除位置,如果循环结束后仍未找到需要删除的元素,则说明链表中无该元素,那么return结束
3.若找到需要删除元素,则进行操作p->next=p->next->next;删除操作完成
链表的优势:链表不需要预先分配空间,只要空间允许,链表中的元素个数就没有限制。
链表的插入和删除操作无需移动数据,只需要修改指针,时间复杂度为O(1)。对于需要频繁进行插入和删除的线性表,宜采用链表。
劣势:用链表查找元素时,只能从表头开始,依次向后遍历,直到找到第i个位置的元素,时间复杂度为O(n),相较于顺序表更复杂。