“ Ctrl AC!一起 AC!”
目录
前言:
讲单链表前,先说一下数组:
数组是一种线性数据结构,它可以实现对数据元素的随机访问,但当在有序数组中插入或删除数据且保持有序性时需移动大量元素;同时数组在内存中占用连续的储存空间,在定义时大小固定,当数据量超过数组容量时,不能动态扩展新的存储空间。
而同为线性数据结构的链表可以很好解决上述问题。链表是线性结构的另一种有效存储结构,它为线性结构中的各元素独立地申请存储空间,并且在每个元素内增设指针来记录其前驱或后继元素的位置。因此能提高内存空间的利用率和动态扩展。
单链表的定义及结点:
单链表的定义:
单链表是由一连串的结构(称为结点)组成的,其中每个结点除了包含所存储对象外的全部属性外,还包含指向链表中下一个结点的指针。
链表中的最后一个结点包含空指针,并通过一个额外的指针记住第一个结点的位置。
单链表结点的结构体:
//第一种(推荐)
struct node
{
int data;
struct node* next;
};
typedef struct node linknode;
typedef linknode* linklist;
linklist p;//定义链表结点指针
//第二种
struct node
{
int data;
stuct node* next;
}linknode;
linknode* p;//定义链表结点指针
这样就能通过指针找到下一结点。
单链表的建立:
在单链表中插入一个数据为x的新结点:
先准备一个指针:
linklist q;
q=(linklist)malloc(sizeof(linknode)) //申请内存
q->data = x //存入数据
插入第一种情况(插入到链表最前面或插入到一个空链表)
q->next = head;
head = q;
插入第二种情况(插入到p指向的结点的后面(p!=尾指针))
q->next = p->next;
p->next = q;
插入第三种情况(插入到最末尾,tail为尾指针)
tail->next = q;
tail = q;
tail = NULL
尾插法建立链表:
linklist creatLink()
{
linklist head = NULL, tail == NULL, q; //初始空链表,q为临时结点
int x;
printf("请输入整数序列,以-1结束\n");
scanf("%d", &x);
while (x != -1)
{
q = (linklist)malloc(sizeof(linknode));
q->data = x;
if (head == NULL)//链表为空
head = tail = q;
else//链表不为空
{
tail->next = q;
tail = q;
}
scanf("%d", &x);
}
if (tail != NULL) tail->next = NULL;//链表置尾结束
return head;
}
单链表的遍历:
遍历释放内存:
链表建立过程中申请来的空间用完后需要释放掉,可通过遍历释放。
如码:
void freeLinklist(linklist head) {//传入一个链表
linklist p;
while (head != NULL) {//遍历链表
p = head;//用p记住待释放的结点
head = head->next;//head结点移动
free(p);//释放
}
}
遍历输出数据:
如码:
void print(linklist head) {
linklist p = head;
while (p != NULL) {
printf("%d ", p->data);//输出
p = p->next;//移动
}
}
单链表查找并删除结点:
查找结点核心代码:
while (p != NULL && p->data != x) {
p=p->next //没结束或不是要找的x就继续遍历
}
删除结点核心代码:
//第一种,删除第一个结点:
head = p->next;
free(p);
//第二种,非首结点(pre为p的前驱结点)
pre->next = p->next;
free(p);
查找并删除结点函数:
linklist deleteList(linklist head, int x) {//x为要删除的结点的数据值
linklist pre = NULL, p = head;
while (p != NULL && p->data != x) {
pre = p;//用pre及时记录p的前驱结点
p = p->next;
}
if (p) {
if (pre == NULL) {//如果删除的是首结点
head = head->next;
}
else {
pre->next = p->next;
}
free(p);
}
return head;
}
例题:
如题:
分析:
直接通过单链表建立函数,最大最小值删除函数,输出答案函数解题:
如码:
#include <stdio.h>
#include <stdlib.h>
int maxx = -1000, minn = 1000;//记录最高最低分
struct node {
int data;
struct node* next;
};
typedef struct node linknode;
typedef linknode* linklist;
linklist scan()/*建立链表*/
{
linklist head = NULL, tail = NULL, p;
int x;
printf("输入各个评委的打分 输出-1结束\n");
scanf("%d", &x);
if (x != -1) {//时刻记录最高最低分
maxx = x > maxx ? x : maxx;
minn = x < minn ? x : minn;
}
while (x != -1) {
p = (linklist)malloc(sizeof(linknode));
p->data = x;
if (head == NULL)
head = tail = p;
else {
tail->next = p;
tail = p;
}
scanf("%d", &x);
if (x != -1) {//时刻记录最高最低分
maxx = x > maxx ? x : maxx;
minn = x < minn ? x : minn;
}
}
if (tail != NULL) tail->next = NULL;
return head;//返回建立完的链表
}
linklist deletemax(linklist head) {/*删除最高分*/
linklist pre, p;
pre = NULL;
p = head;
while (p != NULL && p->data != maxx) {//找到最高分所在的节点
pre = p;
p = p->next;
}
if (pre == NULL) head = head->next;
else pre->next = p->next;
free(p);
return head;//返回修改后的链表
}
linklist deletemin(linklist head) {/*删除最低分*/
linklist pre, p;
pre = NULL;
p = head;
while (p != NULL && p->data != minn) {//找到最低分所在的节点
pre = p;
p = p->next;
}
if (pre == NULL) head = head->next;
else pre->next = p->next;
free(p);
return head;//返回修改后的链表
}
void print(linklist head) {/*输出答案*/
linklist p = head;
double sum = 0; double geshu = 0;
printf("New list:\n");
while (p != NULL) {
printf("%d ", p->data);
sum += p->data;
geshu++;
p = p->next;
}
printf("\n");
printf("最终得分是:%.2lf\n", (sum / geshu));
}
void freeLinklist(linklist head) {/*释放内存*/
linklist p;
while (head != NULL) {
p = head;
head = head->next;
free(p);
}
}
int main()
{
linklist head = scan();//建立单链表
head = deletemax(head);//删除最高分
head = deletemin(head);//删除最低分
print(head);//输出答案
freeLinklist(head);//释放内存
return 0;
}
输出情况:
感谢阅读!!!
“ Ctrl AC!一起 AC!”