1、链表的定义
链表是由一连串的结构(称为结点)组成的,其中每个节点包含指向链表中下一个结点的指针(除最后一个结点为空指针),其中每个结点可以含有若干个存储数据的数据域。
2、优缺点
相比较于数组,使用链表结构可以克服数组需要预先知道数据大小的缺点,可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。
单链表的结构图:
3、单链表的C语言实现
(1)类型声明
#include <stdlib.h> #include <stdbool.h> #define DATA_TYPE int struct node; typedef struct node* List; typedef struct node* Position; List New_List(List head,DATA_TYPE X); //新建链表 bool is_empty(List head); //判定该链表是否为空 bool is_last(Position P); //判定位置P是否为链表的末尾 Position Find(DATA_TYPE X, List head); //查找元素,返回指向该元素的指针 void Delete(DATA_TYPE X, List head); //删除元素 void Insert(DATA_TYPE X, List head); //插入元素 List Delete_list(List head); //删除链表 struct node { DATA_TYPE data; Position next; };
(2)新建链表操作
List New_List(List head,DATA_TYPE X) { Position new_node; if (!is_empty) { printf("链表已存在\n"); return NULL; } new_node = malloc(sizeof(struct node)); if (new_node == NULL) { printf("分配失败\n"); return NULL; } head = NULL; new_node->data = X; new_node->next = head; head = new_node; return head; }
图示:
(3)判断链表是否为空以及判断目标结点是否为该链表最后一个结点
bool is_empty(List head) { return head->next == NULL; } bool is_last(Position P) { return P->next == NULL; }
(4)查找目标结点X
Position Find(DATA_TYPE X, List head) { Position TmpPt; for (TmpPt = head; TmpPt->next != NULL; TmpPt = TmpPt->next) if (TmpPt->data == X) return TmpPt; return NULL; }
(5)删除目标结点X
void Delete(DATA_TYPE X, List head) { Position cur, prev,TmpPt; //prev指向cur的前一节点 TmpPt = head; for (cur = head, prev = NULL; cur != NULL&&cur->data != X; prev = cur, cur = cur->next); if (cur == NULL) return head; //数据X未找到 if (prev == NULL) TmpPt = TmpPt->next; //数据X在头结点 else prev->next = cur->next; //在其他结点 free(cur); return TmpPt; }
在下列链表中,我们假设需要删除的结点为40。
(6)插入结点X
void Insert(DATA_TYPE X, List head) { Position TmpPt, new_node; new_node = malloc(sizeof(struct node)); if (new_node == NULL) { printf("无法分配新结点\n"); return NULL; } new_node->data = X; new_node->next = head; head = new_node; }
图示:
List Delete_list(List head) { Position P, TmpPt; P = head->next; head->next = NULL; while (P != NULL) { TmpPt = P->next; free(P); P = TmpPt; } free(head); return NULL; }
(4)数据结构算法题
题目描述:假设一个算术表达式中可以包含三种括号:圆括号“(”和“)”,方括号“[”和“]”和花括号“{”和“}”,且这三种括号可按任意的次序嵌套使用(如:…[…{… …[…]…]…[…]…(…)…)。编写判别给定表达式中所含括号是否正确配对出现的算法。输出结果YES 或者 NO。
输入:5+{[2X5]+2}
输出:NO
#include<stdio.h> #include<stdlib.h> #define LEN 10000 void push_stack(const char par); int pop_stack(const char par); void clear_stack(void); struct node { char par; struct node *next; }; struct node *top = NULL; struct node *new_node; char bracket[LEN + 1]; int main() { int i, j; scanf("%s", bracket); for (j = 0;; j++) { if (bracket[j] == '(' || bracket[j] == '[' || bracket[j] == '{') push_stack(bracket[j]); else if (bracket[j] == ')' || bracket[j] == ']' || bracket[j] == '}') { if (pop_stack(bracket[j]) == -1) break; } else if (bracket[j] == '\0') { if (top != NULL) { printf("NO\n"); break; } printf("YES\n"); break; } else continue; } clear_stack(); return 0; } void push_stack(const char par) { new_node = (struct node *)malloc(sizeof(struct node)); if (new_node == NULL) exit(EXIT_FAILURE); new_node->par = par; new_node->next = top; top = new_node; } int pop_stack(const char par) { struct node *TmpPt; if (par == ')') { if (top == NULL) { printf("NO\n"); return -1; } if (top->par != '(') { printf("NO\n"); return -1; } else { TmpPt = top; top = top->next; free(TmpPt); } } else if (par == ']') { if (top == NULL) { printf("NO\n"); return -1; } if (top->par != '[') { printf("NO\n"); return -1; } else { TmpPt = top; top = top->next; free(TmpPt); } } else if (par == '}') { if (top == NULL) { printf("NO\n"); return -1; } if (top->par != '{') { printf("NO\n"); return -1; } else { TmpPt = top; top = top->next; free(TmpPt); } } return 0; } void clear_stack(void) { struct node *TmpPt; while (top != NULL) { TmpPt = top; top = top->next; free(TmpPt); } }