赞
踩
目录
链表的两种结构
物理结构和逻辑结构
物理 存储单元 上非连续、非顺序的 存储结构,
逻辑上是连续的,他们之间用指针连续起来
链表中每一个元素称为节点,由一系列的节点组成。
每个节点包括两部分,存储数据元素的数据域(data)和存储下一个节点地址的指针域(next)。
如图所示:下图有四个节点,头节点一般不存数据,head为头节点,next为指向下一个节点的
指针(存储下一个节点的地址),单向不循环链表最后一个节点的指针域,指向空(NULL)。
-
- /**************设计节点类型**************/
- typedef struct ListNode
- {
- int data; //数据域
- struct ListNode *next; //地址域
- } node_t;
申请头节点空间
- /********创建链表********/
- node_t *CreateList()
- {
- node_t *head = (node_t *)malloc(sizeof(node_t)); //申请头节点空间
- if (head == NULL)
- {
- perror("head is null\n"); //如果空间申请失败报错
- return NULL;
- }
- head->data = 0; //头节点数据域不放数据,初始化
- head->next = NULL;
-
- return head;
- }
- /************头插法************/
- int InsertHListNode(node_t *head, int newdata)
- {
- // 1、判断
- if (head == NULL)
- {
- perror("head is null\n");
- return -1;
- }
- // 2、申请新节点空间
- node_t *newnode = (node_t *)malloc(sizeof(node_t));
- if (newnode == NULL)
- {
- perror("newnode is null\n");
- return -1;
- }
- // 3、填写数据
- newnode->data = newdata;
- // 4、修改指针
- newnode->next = head->next;
- head->next = newnode; //头节点指向新节点
- return 0;
- }
头插法就是在头节点后插入新节点(头节点不放数据所以从头节点后一个位置插入),核心就是 将新节点两条线连接起来
- /************尾插法************/
- int InserttListNode(node_t *head, int newdata)
- {
- // 1、判断
- if (head == NULL)
- {
- perror("head is null\n");
- return -1;
- }
- // 2、申请新节点空间
- node_t *newnode = (node_t *)malloc(sizeof(node_t));
- if (newnode == NULL)
- {
- perror("malloc error\n");
- return -1;
- }
- // 3、填写数据
- newnode->data = newdata;
- // 4、找尾
- node_t *temp = head; //因为头节点不能动所以申请一个中间变量
- while (temp->next != NULL) //当temp->next = NULL时跳出循环
- {
- temp = temp->next;
- }
-
- // 5、修改指针
- newnode->next = temp->next; //新节点指向最后
- temp->next = newnode; //新节点接到最后一个节点后
- return 0;
- }
尾插法 核心就是找尾,找到尾后修改指针的指向,代码中的指针指向跟图中的指针指向是同一个意思,只是写法不同。
遍历, 循环打印,将链表中的所有的节点数据打印到终端
- /*************打印链表***************/
- void PrintList(node_t *head)
- {
- if (head == NULL)
- {
- perror("There is no data in the linked list, please input it first\n");
- return;
- }
-
- node_t *temp = head;
- while (temp->next != NULL)
- {
- temp = temp->next; //因为头节点不放数据所以从第二个节点开始
- printf("%d\t", temp->data);
- }
- printf("\n");
- }
- /***************头删法*******************/
- int DeleteHList(node_t *head)
- {
- if (head == NULL)
- {
- perror("head is null\n");
- return -1;
- }
- //设置一个临时变量
- node_t *temp = head->next;
- head->next = temp->next;
- free(temp); //删除成功释放空间
- temp = NULL;
- return 0;
- }
头删法:相对来说是比较简单的,只需要改变一个指针指向。
- /***************尾删法*******************/
- int DeleteTList(node_t *head)
- {
- if (head == NULL)
- {
- perror("head is null\n");
- return -1;
- }
- //设置一个临时变量
- node_t *prev = NULL; //指向尾的前一个节点
- node_t *temp = head;
- //找尾
- while (temp->next->next != NULL)
- {
- temp = temp->next;
- }
- prev = temp;
- temp = temp->next;
- prev->next = NULL;
- free(temp);
- temp = NULL;
- return 0;
- }
尾删法:找两个节点先找倒是第二个,在通过倒数第二个找到最后一个,找最后一个是为了释放节点空间。
遍历整个链表,然后返回节点数据个数(因为头节点不放数据所以不包括头节点)
- /****************链表的节点元素个数**********************/
- int ListLength(node_t *head)
- {
- if (head == NULL)
- {
- perror("head is null\n");
- return -1;
- }
- node_t *temp = head;
- int i = 0;
- while (temp->next != NULL)
- {
- temp = temp->next;
- i++;
- }
- return i;
- }
- /***************指定位置插入***************/
- int InsertLocaList(node_t *head, int newdata, int loca)
- {
- //判错
- int len = ListLength(head);
- if (head == NULL || loca <= 0 || loca > len + 1) //插入的位置超范围
- {
- perror("head is null or out of scope\n");
- return -1;
- }
- //申请新节点空间
- node_t *newnode = (node_t *)malloc(sizeof(node_t));
- if (newnode == NULL)
- {
- perror("malloc error\n");
- return -1;
- }
- //填写数据,建立联系
- newnode->data = newdata;
- node_t *temp = head;
- int i = 1;
- while (loca != i)
- {
- temp = temp->next;
- i++;
- }
- newnode->next = temp->next;
- temp->next = newnode;
- return 0;
- }
在写之前一定要判断该链表和该位置是否为空,如果都不存在链表和该位置,要插入的节点就接不上了。
- /***************指定位置删除***************/
- int DeleteLocaList(node_t *head, int loca)
- {
- //判错
- int len = ListLength(head);
- if (head == NULL || loca <= 0 || loca > len) //删除的位置超范围
- {
- perror("head is null or out of scope\n");
- return -1;
- }
-
- node_t *prev = NULL; //指向尾的前一个节点
- node_t *temp = head;
- int i = 1;
- //找要删除节点的前一个位置
- while (loca != i)
- {
- temp = temp->next;
- i++;
- }
- prev = temp;
- temp = temp->next;
- prev->next = temp->next;
- return 0;
- }
- /************链表冒泡排序*************/
- node_t *SortList(node_t *head)
- {
- if (head == NULL)
- {
- perror("head is null\n");
- return NULL;
- }
- int len = ListLength(head);
- if (len < 2)
- {
- return head;
- }
- node_t *r, *p, *q; //表示前中后三个节点位置
- r = head;
- for (int i = 0; i < len - 1; i++)
- {
- r = head;
- for (int j = 0; j < len - i - 1; j++)
- {
- p = r->next;
- q = p->next;
- if (q->data < p->data)
- {
- p->next = q->next;
- q->next = p;
- r->next = q;
- }
- r = r->next;
- }
- }
- return head;
- }
- void menu(node_t *head)
- {
- char ch;
- while (1)
- {
- printf("***************************************\n");
- printf("***** 1.头插 *****\n");
- printf("***** 2.尾插 *****\n");
- printf("***** 3.头删 *****\n");
- printf("***** 4.尾删 *****\n");
- printf("***** 5.在指定位置插入 *****\n");
- printf("***** 6.在指定位置删除 *****\n");
- printf("***** 7.打印单链表 *****\n");
- printf("***** 8.查看链表中有多少元素 *****\n");
- printf("***** 9.排序 *****\n");
- printf("***** 0.退出 *****\n");
- printf("***************************************\n");
-
- int option = 0, loca = 0, newdata = 0;
- printf("请输入选项:> ");
- scanf("%d", &option);
- switch (option)
- {
- case 9:
- head = SortList(head);
- break;
- case 8:
- printf("链表中有%d个元素\n", ListLength(head));
- break;
- case 7:
- PrintList(head);
- break;
- case 6:
- printf("请输入你要删除的位置:");
- scanf("%d", &loca);
- DeleteLocaList(head, loca);
- break;
- case 5:
- printf("请输入你要插入的位置:");
- scanf("%d", &loca);
- printf("请输入你要插入的元素:");
- scanf("%d", &newdata);
- InsertLocaList(head, newdata, loca);
- break;
- case 4:
- DeleteTList(head);
- break;
- case 3:
- DeleteHList(head);
- break;
- case 2:
- printf("请输入你要插入的元素:");
- scanf("%d", &newdata);
- InserttListNode(head, newdata);
- break;
- case 1:
- printf("请输入你要插入的元素:");
- scanf("%d", &newdata);
- InsertHListNode(head, newdata);
- break;
- case 0:
- return;
- default:
- printf("输入错误\n");
- break;
- }
- printf("是否继续(y/n)\n");
- getchar(); //空吞
- ch = getchar();
- if (ch == 'n' || ch == 'N')
- {
- return;
- }
- }
- }
- #include <stdio.h>
- #include <stdlib.h>
-
- /**************设计节点类型**************/
- typedef struct ListNode
- {
- int data; //数据域
- struct ListNode *next; //地址域
- } node_t;
-
- node_t *CreateList(); //创建链表
- int InsertHListNode(node_t *head, int newdata); //头插法
- int InserttListNode(node_t *head, int newdata); //尾插法
- int InsertLocaList(node_t *head, int newdata, int loca); //在指定位置插入
- int DeleteHList(node_t *head); //头删法
- int DeleteTList(node_t *head); //尾删法
- int DeleteLocaList(node_t *head, int loca); //在指定位置删除
- int ListLength(node_t *head); //链表的节点元素个数
- void PrintList(node_t *head); //打印链表
- void menu(node_t *head); //菜单
- node_t *SortList(node_t *head); //冒泡排序
-
- int main()
- {
- node_t *head = CreateList();
- if (head == NULL)
- {
- perror("head is null\n");
- return -1;
- }
- menu(head);
- return 0;
- }
-
- /*****************菜单***********/
- void menu(node_t *head)
- {
- char ch;
- while (1)
- {
- printf("***************************************\n");
- printf("***** 1.头插 *****\n");
- printf("***** 2.尾插 *****\n");
- printf("***** 3.头删 *****\n");
- printf("***** 4.尾删 *****\n");
- printf("***** 5.在指定位置插入 *****\n");
- printf("***** 6.在指定位置删除 *****\n");
- printf("***** 7.打印单链表 *****\n");
- printf("***** 8.查看链表中有多少元素 *****\n");
- printf("***** 9.排序 *****\n");
- printf("***** 0.退出 *****\n");
- printf("***************************************\n");
-
- int option = 0, loca = 0, newdata = 0;
- printf("请输入选项:> ");
- scanf("%d", &option);
- switch (option)
- {
- case 9:
- head = SortList(head);
- break;
- case 8:
- printf("链表中有%d个元素\n", ListLength(head));
- break;
- case 7:
- PrintList(head);
- break;
- case 6:
- printf("请输入你要删除的位置:");
- scanf("%d", &loca);
- DeleteLocaList(head, loca);
- break;
- case 5:
- printf("请输入你要插入的位置:");
- scanf("%d", &loca);
- printf("请输入你要插入的元素:");
- scanf("%d", &newdata);
- InsertLocaList(head, newdata, loca);
- break;
- case 4:
- DeleteTList(head);
- break;
- case 3:
- DeleteHList(head);
- break;
- case 2:
- printf("请输入你要插入的元素:");
- scanf("%d", &newdata);
- InserttListNode(head, newdata);
- break;
- case 1:
- printf("请输入你要插入的元素:");
- scanf("%d", &newdata);
- InsertHListNode(head, newdata);
- break;
- case 0:
- return;
- default:
- printf("输入错误\n");
- break;
- }
- printf("是否继续(y/n)\n");
- getchar(); //空吞
- ch = getchar();
- if (ch == 'n' || ch == 'N')
- {
- return;
- }
- }
- }
-
- /********创建链表********/
- node_t *CreateList()
- {
- node_t *head = (node_t *)malloc(sizeof(node_t)); //申请头节点空间
- if (head == NULL)
- {
- perror("head is null\n"); //如果空间申请失败报错
- return NULL;
- }
- head->data = 0; //头节点数据域不放数据,初始化
- head->next = NULL;
-
- return head;
- }
-
- /************头插法************/
- int InsertHListNode(node_t *head, int newdata)
- {
- // 1、判断
- if (head == NULL)
- {
- perror("head is null\n");
- return -1;
- }
- // 2、申请新节点空间
- node_t *newnode = (node_t *)malloc(sizeof(node_t));
- if (newnode == NULL)
- {
- perror("newnode is null\n");
- return -1;
- }
- // 3、填写数据
- newnode->data = newdata;
- // 4、修改指针
- newnode->next = head->next;
- head->next = newnode; //头节点指向新节点
- return 0;
- }
-
- /************尾插法************/
- int InserttListNode(node_t *head, int newdata)
- {
- // 1、判断
- if (head == NULL)
- {
- perror("head is null\n");
- return -1;
- }
- // 2、申请新节点空间
- node_t *newnode = (node_t *)malloc(sizeof(node_t));
- if (newnode == NULL)
- {
- perror("malloc error\n");
- return -1;
- }
- // 3、填写数据
- newnode->data = newdata;
- // 4、找尾
- node_t *temp = head; //因为头节点不能动所以申请一个中间变量
- while (temp->next != NULL) //当temp->next = NULL时跳出循环
- {
- temp = temp->next;
- }
-
- // 5、修改指针
- newnode->next = temp->next; //新节点指向最后
- temp->next = newnode; //新节点接到最后一个节点后
- return 0;
- }
-
- /*************打印链表***************/
- void PrintList(node_t *head)
- {
- if (head == NULL)
- {
- perror("There is no data in the linked list, please input it first\n");
- return;
- }
-
- node_t *temp = head;
- while (temp->next != NULL)
- {
- temp = temp->next; //因为头节点不放数据所以从第二个节点开始
- printf("%d\t", temp->data);
- }
- printf("\n");
- }
-
- /***************头删法*******************/
- int DeleteHList(node_t *head)
- {
- if (head == NULL)
- {
- perror("head is null\n");
- return -1;
- }
- //设置一个临时变量
- node_t *temp = head->next;
- head->next = temp->next;
- free(temp); //删除成功释放空间
- temp = NULL;
- return 0;
- }
-
- /***************尾删法*******************/
- int DeleteTList(node_t *head)
- {
- if (head == NULL)
- {
- perror("head is null\n");
- return -1;
- }
- //设置一个临时变量
- node_t *prev = NULL; //指向尾的前一个节点
- node_t *temp = head;
- //找尾
- while (temp->next->next != NULL)
- {
- temp = temp->next;
- }
- prev = temp;
- temp = temp->next;
- prev->next = NULL;
- free(temp);
- temp = NULL;
- return 0;
- }
-
- /****************链表的节点元素个数**********************/
- int ListLength(node_t *head)
- {
- if (head == NULL)
- {
- perror("head is null\n");
- return -1;
- }
- node_t *temp = head;
- int i = 0;
- while (temp->next != NULL)
- {
- temp = temp->next;
- i++;
- }
- return i;
- }
-
- /***************指定位置插入***************/
- int InsertLocaList(node_t *head, int newdata, int loca)
- {
- //判错
- int len = ListLength(head);
- if (head == NULL || loca <= 0 || loca > len + 1) //插入的位置超范围
- {
- perror("head is null or out of scope\n");
- return -1;
- }
- //申请新节点空间
- node_t *newnode = (node_t *)malloc(sizeof(node_t));
- if (newnode == NULL)
- {
- perror("malloc error\n");
- return -1;
- }
- //填写数据,建立联系
- newnode->data = newdata;
- node_t *temp = head;
- int i = 1;
- while (loca != i)
- {
- temp = temp->next;
- i++;
- }
- newnode->next = temp->next;
- temp->next = newnode;
- return 0;
- }
-
- /***************指定位置删除***************/
- int DeleteLocaList(node_t *head, int loca)
- {
- //判错
- int len = ListLength(head);
- if (head == NULL || loca <= 0 || loca > len) //删除的位置超范围
- {
- perror("head is null or out of scope\n");
- return -1;
- }
-
- node_t *prev = NULL; //指向尾的前一个节点
- node_t *temp = head;
- int i = 1;
- //找要删除节点的前一个位置
- while (loca != i)
- {
- temp = temp->next;
- i++;
- }
- prev = temp;
- temp = temp->next;
- prev->next = temp->next;
- return 0;
- }
-
- /************链表冒泡排序*************/
- node_t *SortList(node_t *head)
- {
- if (head == NULL)
- {
- perror("head is null\n");
- return NULL;
- }
- int len = ListLength(head);
- if (len < 2)
- {
- return head;
- }
- node_t *r, *p, *q; //表示前中后三个节点位置
- r = head;
- for (int i = 0; i < len - 1; i++)
- {
- r = head;
- for (int j = 0; j < len - i - 1; j++)
- {
- p = r->next;
- q = p->next;
- if (q->data < p->data)
- {
- p->next = q->next;
- q->next = p;
- r->next = q;
- }
- r = r->next;
- }
- }
- return head;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。