鞍山市网站建设_网站建设公司_Sketch_seo优化
2025/12/22 22:42:38 网站建设 项目流程

一、链表

1.线性链表:
链表是一组存储线性表的数据元素存储单元;
由若干个节点组成,结点包括两个域:
其中存储数据元素信息的称为数据域;存储直接后继存储位置有域称为指针域。

2.链表的基本操作:
(1)链表存储结构

typedef int ElemType;
typedef struct node
{ElemType data;  //数据域struct node *next;  //指针域
} Node;

(2)单链表-初始化

Node* initList()
{Node *head = (Node*)malloc(sizeof(Node));head->data = 0;head->next = NULL;return head;
}
int main ()
{Node *list = initList();return 1;
}

(3)单链表-头插法

int insertHead (Node* L, ElemType e)
{Node *p = (Node*)malloc(sizeof(Node));p->data = e;p->next = L->next;L->next = p;
}
int main ()
{Node *list = initList();insertHead(list, 10);insertHead(list, 20);
}

(4)单链表-遍历

void listNode (Node* L)
{Node *p = L->next;while (p != NULL){printf ("%dn", p->data) ;p = p->next;}printf("\n");
}

(5)单链表-获取链表长度

int listLength (Node *L)
{Node *p = L;int len = 0;while (p != NULL){p = p->next;len++;}return len;
}

(6)单链表-尾插法

Node* get_tail (Node *L)
{Node *p = L;while (p->next != NULL){p = p->next;}return p;
}

(7)单链表-在指定位置插入数据

int insertNode(Node *L, int pos, ElemType e)
{Node *p = L;int i = 0;while(i < pos-1){p = p->next;i++;if (p == NULL)return 0;}Node *q = (Node*)malloc(sizeof(Node));q->data = e;q->next = p->next;p->next = q;return 1;
}

(8)单链表-删除节点

int deleteNode(Node *L, int pos)
{Node *p = L;int i = 0;while(i < pos-1){p = p->next;i++;if (p == NULL){return 0;}}if(p->next == NULL){printf("要删除的位置错误\n");return 0;}Node *q = p->next;p->next = q->next;free(q);return 1;
}

(9)单链表-释放链表

void freeList (Node *L)
{Node *p = L->next;Node *q;while (p != NULL){q = p->next;free (p) ;p = q;}L->next = NULL;
}

3.双向链表:

链式存储结构的节点中只有一个指示直接后继的指针域,由此,从某个结点出发只能顺指针向后寻查其他节点。若要寻查结点的直接前驱、则必须从表头指针出发。换句话说,在单链表中,查找直接后继的执行时间为O(1),而查找直接前驱的执行时间为O(n)。为克服单链表这种单向性的缺点,可利用双向链表。在双向链表的节点中有两个指针域,一个指向直接后继,另一个指向直接前驱。

双向链表的结构

typedef int ElemType;typedef struct node
{ElemType data;struct node *prev, *next; //prev为前驱结点,next为后继结点
} Node;

二、栈

1.栈(stack)是限定仅在表尾进行插入或删除操作的线性表。
因此对栈来说,表尾端有其特殊含义,称为栈顶(top),相应地,表头端称为栈底(bottom)。不含元素的空表称为空栈。
假设S=(a1,a2,…,an),则称a1为栈底元素,an为栈顶元素。栈中元素按a1,a2,…,an的次序进栈,退栈的第一个元素应为栈顶元素。换句话说,栈的修改是按照后进先出的原则进行的。
因此,栈又称为后进先出(Last In First Out,LIFO)的线性表。
栈是限制插入和删除操作只能在一个位置进行的表,该位置是表的末端,叫作栈顶(top)。对栈的基本操作有进栈(push)和出栈(Pop),前者相当于插入,后者则是删除最后插入的元素。

2.栈的基本操作:

(1)栈的链式结构实现:

typedef int ElemType;
typedef struct stack
{ElemType data;struct stack *next;
} Stack;

(2)栈的链式结构实现-初始化:

typedef int ElemType;
typedef struct stack
{ElemType data;struct stack *next;
} Stack;
Stack* initStack ()
{Stack *s = (Stack*)malloc(sizeof(Stack));s->data = 0;s->next = NULL;return s;
}

(3)栈的链式结构实现-判断栈是否为空

int isEmpty (Stack *s)
{if (s->next == NULL){printf("空的\n");return 1;}else{return 0;}
}

(4)栈的链式结构实现-进栈/压栈

int push (Stack *s, ElemType e)
{Stack *p = (Stack*)malloc(sizeof(Stack));p->data = e;p->next = s->next;s->next = p;return 1;
}

(5)栈的链式结构实现-出栈

int pop(Stack *s, ElemType *e)
{if (s->next == NULL){printf("空的\n");return 0;}*e = s->next->data;Stack *q = s->next;s->next = q->next;free (q) ;return 1;
}

(6)栈的链式结构实现-获取栈顶元素

int getTop(Stack *s, ElemType *e)
{if (s->next == NULL){printf("空的\n");return 0;}*e = s->next->data;return 1;
}

三、队列

1.队列(queue)是一种先进先出的线性表。
它只允许在表的一端进行插入,而在另一端删除元素。在队列中,允许插入的一端称为队尾,允许删除的一端则称为队头。假设队列为q=(a1,a2,…,an),那么,a1就是队头元素,an就是队尾元素。
队列中的元素是按照a1,a2,…,an的顺序进入的,退出队列也只能按照这个次序依次退出,也就是说,只有在a1,a2,…,an-1都离开队列之后,an才能退出队列。

2.队列的基本操作:

(1)队列的链式结构-初始化

Queue* initQueue ()
{Queue *q = (Queue*) malloc(sizeof (Queue));QueueNode *node = (QueueNode*)malloc(sizeof (QueueNode)) ;node->data = 0;node->next = NULL;q->front = node;q->rear = node;return q;
}

(2)队列的链式结构

typedef struct QueueNode
{ElemType data;struct QueueNode *next;
} QueueNode;
typedef struct
{QueueNode *front;QueueNode *rear;
} Queue;

(3)队列的链式结构-初始化

Queue* initQueue ()
{Queue *q = (Queue*)malloc(sizeof (Queue));QueueNode *node = (QueueNode*)malloc(sizeof (QueueNode));node->data = 0;node->next = NULL;q->front = node;q->rear = node;return q;
}  

(4)队列的链式结构-判断队列是否为空

int isEmpty (Queue *q)
{if (q->front == q->rear){return 1;}else{return 0;}
}

(5)队列的链式结构-入队

void equeue (Queue *q, ElemType e)
{QueueNode *node = (QueueNode*) malloc(sizeof (QueueNode)) ;node->data = e;node->next = NULL;q->rear->next = node;q->rear = node;
}

(6)队列的链式结构-出队

int dequeue(Queue *q, ElemType *e)
{QueueNode *node = q->front->next;*e = node->data;q->front->next = node->next;if (q->rear == node){q->rear = q->front;}free (node) ;return 1;
}

(7)队列的链式结构-获取队头元素

ElemType getFront (Queue *q)
{if (isEmpty (q)){printf("空的\n");return 0;}return q->front->next->data;
}

四、总结

1.基本操作的实现共性与差异
(1)共性
1.存储基础:链表、栈(链式)、队列(链式)均基于节点 + 指针的链式存储结构,通过动态内存分配(malloc)创建节点,借助指针维护元素间的逻辑关系,最终都需通过free释放内存以避免泄漏。

2.初始化逻辑:三者初始化均需创建头节点(或头指针),并将指针域置空(NULL),为后续操作建立初始的空结构。

3.遍历 / 访问逻辑:都需通过指针遍历节点实现元素访问,且访问过程中需判断指针是否为空以防止越界。
(2)差异

结构 核心操作位置 核心操作 时间复杂度(核心操作) 典型应用场景
单链表 任意位置 头插、尾插、指定位置插入 / 删除 插入 / 删除 O (1)(已知位置)、遍历 O (n) 动态数据存储、不定长数据管理
双向链表 任意位置 前驱 / 后继节点的查找与操作 查找前驱 O (1)、其他同单链表 需频繁查找前驱的场景(如链表排序)
栈(链式) 栈顶 压栈、出栈 压栈 / 出栈 O (1) 表达式求值、函数调用栈、回溯算法
队列(链式) 队尾(插入)、队头(删除) 入队、出队 入队 / 出队 O (1) 任务排队、消息队列、广度优先搜索

2.实现中的注意事项与易错点
(1)内存管理:链式结构中每次创建节点都需通过malloc分配内存,操作完成后必须通过free释放节点,否则会导致内存泄漏;同时需避免野指针。

(2)边界条件判断:

1.链表:插入 / 删除时需判断位置是否合法、遍历到链表尾部时需判断p->next是否为空;

2.栈:出栈和获取栈顶元素时需先判断栈是否为空;

3.队列:出队时需判断队列是否为空,且当最后一个节点出队时需将队尾指针重置为队头指针,避免野指针。

(3)指针操作顺序:插入节点时需先维护后继节点的指针关系,再修改前驱节点的指针,否则会导致链表断裂。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询