单向链表和双向链表分析与操作

单向链表和双向链表分析与操作单链表和双链表链表结构 优点 1 在程序中使用数组之前 必须事先知道数组的大小 增加数组的大小是一个耗时的过程 在运行时几乎不可能扩展数组的大小 而链表不需要提前声明链表的大小 链表的大小是随着使用的过程逐步增大的 2 在空间的利用上链表相比数组要更加灵活 不会造成内存的大量浪费 3 向链表中插入或从链表中删除一项的操作不需要移动很多项 只涉及常数个节点链的改变 时间复杂度为 O 1 缺点 由于在链表中 仅仅只有头节点和尾节点是可见的 因此要想查找某个节点 必须从头节点或尾节点一路找下去 时间

创建一个链表

例如创建一个存储{1,2,3,4}且无头节点的单链表 实现增删改查

#include <stdio.h> #include <stdlib.h> //1、声明结点结构 typedef struct Link { 
    int elem; //数据域 struct Link* next; //指针域 }link; link* initLink(); //链表插入的函数,p是链表,elem是插入的结点的数据域,add是插入的位置 link* insertElem(link* p, int elem, int add); //删除结点的函数,p代表操作链表,add代表删除节点的位置 link* delElem(link* p, int add); //查找结点的函数,elem为目标结点的数据域的值 int selectElem(link* p, int elem); //更新结点的函数,newElem为新的数据域的值 link* amendElem(link* p, int add, int newElem); void display(link* p); int main() { 
    link* p = NULL; int address; //初始化链表(1,2,3,4) printf("初始化链表为:\n"); p = initLink(); display(p); printf("在第4的位置插入元素5:\n"); p = insertElem(p, 5, 4); display(p); printf("删除元素3:\n"); p = delElem(p, 3); display(p); printf("查找元素2的位置为:\n"); address = selectElem(p, 2); if (address == -1) { 
    printf("没有该元素"); } else { 
    printf("元素2的位置为:%d\n", address); } printf("更改第3的位置上的数据为7:\n"); p = amendElem(p, 3, 7); display(p); return 0; } //2、创建链表(1,2,3,4) link* initLink() { 
    link* p = (link*)malloc(sizeof(link));//创建一个头结点 link* temp = p;//声明一个指针指向头结点,用于遍历链表 int i = 0; //生成链表 for (i = 1; i < 5; i++) { 
    link* a = (link*)malloc(sizeof(link)); a->elem = i; a->next = NULL; temp->next = a; temp = temp->next; } return p; } //插入一个元素 link* insertElem(link* p, int elem, int add) { 
    link* temp = p;//创建临时结点temp link* c = NULL; int i = 0; //首先找到要插入位置的上一个结点 for (i = 1; i < add; i++) { 
    if (temp == NULL) { 
    printf("插入位置无效\n"); return p; } temp = temp->next; } //创建插入结点c c = (link*)malloc(sizeof(link)); c->elem = elem; //向链表中插入结点 c->next = temp->next; temp->next = c; return p; } //删除一个元素 link* delElem(link* p, int add) { 
    link* temp = p; link* del = NULL; int i = 0; //遍历到被删除结点的上一个结点 for (i = 1; i < add; i++) { 
    temp = temp->next; } del = temp->next;//单独设置一个指针指向被删除结点,以防丢失 temp->next = temp->next->next;//删除某个结点的方法就是更改前一个结点的指针域 free(del);//手动释放该结点,防止内存泄漏 return p; } //查找一个元素 int selectElem(link* p, int elem) { 
    link* t = p; int i = 1; while (t->next) { 
    t = t->next; if (t->elem == elem) { 
    return i; } i++; } return -1; } //更新元素 link* amendElem(link* p, int add, int newElem) { 
    int i = 0; link* temp = p; temp = temp->next;//tamp指向首元结点 //temp指向被删除结点 for (i = 1; i < add; i++) { 
    temp = temp->next; } temp->elem = newElem; return p; } void display(link* p) { 
    link* temp = p;//将temp指针重新指向头结点 //只要temp指针指向的结点的next不是Null,就执行输出语句。 while (temp->next) { 
    temp = temp->next; printf("%d ", temp->elem); } printf("\n"); } 

双链表

#include <stdio.h> #include <stdlib.h> typedef struct line { 
    struct line * prior; int data; struct line * next; }line; //双链表的创建 line* initLine(line * head); //双链表插入元素,add表示插入位置 line * insertLine(line * head, int data, int add); //双链表删除指定元素 line * delLine(line * head, int data); //双链表中查找指定元素 int selectElem(line * head, int elem); //双链表中更改指定位置节点中存储的数据,add表示更改位置 line *amendElem(line * p, int add, int newElem); //输出双链表的实现函数 void display(line * head); int main() { 
    line * head = NULL; //创建双链表 printf("初始链表为:\n"); head = initLine(head); display(head); //在表中第 3 的位置插入元素 7 printf("在表中第 3 的位置插入新元素 7:\n"); head = insertLine(head, 7, 3); display(head); //表中删除元素 2 printf("删除元素 2:\n"); head = delLine(head, 2); display(head); printf("元素 3 的位置是:%d\n", selectElem(head, 3)); //表中第 3 个节点中的数据改为存储 6 printf("将第 3 个节点存储的数据改为 6:\n"); head = amendElem(head, 3, 6); display(head); return 0; } line* initLine(line * head) { 
    int i = 0; line * list = NULL; head = (line*)malloc(sizeof(line)); head->prior = NULL; head->next = NULL; head->data = 1; list = head; for (i = 2; i <= 3; i++) { 
    line * body = (line*)malloc(sizeof(line)); body->prior = NULL; body->next = NULL; body->data = i; list->next = body; body->prior = list; list = list->next; } return head; } line * insertLine(line * head, int data, int add) { 
    //新建数据域为data的结点 line * temp = (line*)malloc(sizeof(line)); temp->data = data; temp->prior = NULL; temp->next = NULL; //插入到链表头,要特殊考虑 if (add == 1) { 
    temp->next = head; head->prior = temp; head = temp; } else { 
    int i = 0; line * body = head; //找到要插入位置的前一个结点 for (i = 1; i < add - 1; i++) { 
    body = body->next; if (body == NULL) { 
    printf("插入位置有误\n"); break; } } if (body) { 
    //判断条件为真,说明插入位置为链表尾 if (body->next == NULL) { 
    body->next = temp; temp->prior = body; } else { 
    body->next->prior = temp; temp->next = body->next; body->next = temp; temp->prior = body; } } } return head; } line * delLine(line * head, int data) { 
    line * temp = head; //遍历链表 while (temp) { 
    //判断当前结点中数据域和data是否相等,若相等,摘除该结点 if (temp->data == data) { 
    temp->prior->next = temp->next; temp->next->prior = temp->prior; free(temp); return head; } temp = temp->next; } printf("链表中无该数据元素\n"); return head; } //head为原双链表,elem表示被查找元素 int selectElem(line * head, int elem) { 
    //新建一个指针t,初始化为头指针 head line * t = head; int i = 1; while (t) { 
    if (t->data == elem) { 
    return i; } i++; t = t->next; } //程序执行至此处,表示查找失败 return -1; } //更新函数,其中,add 表示更改结点在双链表中的位置,newElem 为新数据的值 line *amendElem(line * p, int add, int newElem) { 
    int i = 0; line * temp = p; //遍历到被删除结点 for (i = 1; i < add; i++) { 
    temp = temp->next; if (temp == NULL) { 
    printf("更改位置有误!\n"); break; } } if (temp) { 
    temp->data = newElem; } return p; } //输出链表的功能函数 void display(line * head) { 
    line * temp = head; while (temp) { 
    if (temp->next == NULL) { 
    printf("%d\n", temp->data); } else { 
    printf("%d->", temp->data); } temp = temp->next; } } 
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/228399.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月16日 下午7:07
下一篇 2026年3月16日 下午7:07


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号