热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

读《数据结构》14章[线性结构]

2016.06.07–06.30读《数据结构》(严蔚敏吴伟明)“1-4章”的个人笔记。06.071与数据结构相关的理解对数据结构的理解࿰

2016.06.07 – 06.30
读《数据结构》(严蔚敏 吴伟明)“1-4章”的个人笔记。

06.07


1 与数据结构相关的理解

对数据结构的理解(编程语言层面)。数据结构是相互之间存在一种或多种特定关系的数据元素的集合。

例 – 线性链表。

/* 描述数据元素的类型 */
typedef struct _link_list {char ch;int i;struct _link_list *pn;
}LinkList;/* 描述数据元素之间关系的代码 */
...

用LinkList定义一个数据对象(变量)就得到一个数据元素,用LinkList定义多个数据对象就得到数据元素的集合;组织各个数据元素在内存中的存储关系(在内存中连续或者不连续存储)及各个数据元素间(被操作)的联系(如pn指向另外一个数据元素)就得到了各个数据元素之间的关系。

算法。算法是对特定问题求解步骤的一种描述。算法效率的度量需通过依据该算法编制的程序在计算机上运行(时)所消耗的时间来度量[代码的时间复杂度可作为算法执行效率的一种参考]。

时间复杂度。一般情况下,算法中基本操作重复执行的次数是问题规模n的一个函数f(n),算法的复杂度记作T(n) = O(f(n)),表示随问题规模n的增大,算法执行时间的增长率和f(n)的增长率是相同

06.08
f(n)的计算。对于不同的输入该算法有不同的执行次数时,可用平均值作为f(n)的值;有时各种输入数据输入的概率难以确定,所以更可行的方法是使用该算法最坏执行次数的值作为f(n)的值。

算法的存储空间 复杂度。空间复杂度S(n) = O(f(n)),其中n为问题规模。一个上机执行程序除了需要存储空间来寄存本身所用指令、常数、变量和输入数据外,也需要一些对数据进行操作的工作单元和存储一些为实现计算所需信息的存储空间。若输入数据所占空间只取决于问题本身,和算法无关,则只需要分析除输入和程序之外的额外空间。


Part-I 线性结构

线性结构的特点:在数据元素的非空有限集合中,(1) 存在唯一的一个被称做“第一个”的数据元素;(2) 存在唯一的一个被称做“最后一个”的数据元素;(3) 除了第一个外,集合中的每个数据元素均只有一个前驱;(4) 除最后一个外,集合中每个数据元素均只有一个后继。


2 线性表

线性表。一个线性表是n个数据元素(记录,可以有若干个数据项)的有限序列,其长度可变。[含有大量记录的线性表被称为文件]


2.1 顺序表

线性表的顺序表示 – 顺序表。线性表的顺序表示指的是用一组地址连续的存储单元依次存储线性表的数据元素。

例 - 用C语言来实现一个简单的顺序表。先为顺序表动态分配以元素大小为单位的n个空间单元;若往顺序表中插入一个元素时若超过了当前所分配的空间则往当前空间中追加m个空间单元

06.14
[1] 代码简单实现
sequence_list.c

/* sequence_list.c* 实现一个满足线性表的顺序表的定义的顺序表及一些相关的简单操作* 2016.06.13 - 06.14*/
#include
#include /* 函数退出状态 */
#define MALLOCFAILE -1 // 分配空间失败
#define OK 0 // 程序正常返回值
#define FAILE 1 // 函数返回失败/* 线性表的顺序表动态分配顺序存储结构 */
#define LIST_INIT_SIZE 100 // 线性表存储空间的初始分配量
#define LIST_INCREMENT 10 // 线性表存储空间的分配增量
typedef char ElemType;
typedef struct {ElemType *pelem; // 线性表存储空间基址int len; // 线性表长度int lsize; // 线性表当前分配的存储空间
}SqList;/* 为线性表的顺序表创建存储空间 */
int malloc_sq_list(SqList *psql)
{if (!psql) return FAILE;// 构造一个空(无值)的线性表psql->pelem = (ElemType *)malloc(LIST_INIT_SIZE * sizeof(ElemType));if (!psql->pelem) exit(MALLOCFAILE);psql->len = 0;psql->lsize = LIST_INIT_SIZE;return OK;
}/* 释放线性表的顺序表的存储空间 */
void free_sq_list(SqList *psql)
{if (!psql || !psql->pelem) return ;free(psql->pelem);psql->pelem = NULL;psql->len = 0;psql->lsize = 0;
}/* 往线性表的顺序表中插入一个元素 */
int insert_elem2sq_list(SqList *psql, int i, ElemType elem)
{ElemType *newbase, *p, *q;if (!psql || !psql->pelem) return FAILE;// 在顺序线性表psql第i个位置之前插入新的元素elemif (i <1 || i > psql->len &#43; 1) return FAILE;if (psql->len >&#61; psql->lsize) {newbase &#61; (ElemType *)realloc(psql->pelem, \(psql->lsize &#43; LIST_INCREMENT) * sizeof(ElemType));if (!newbase) exit(MALLOCFAILE);psql->pelem &#61; newbase;psql->lsize &#43;&#61; LIST_INCREMENT;}q &#61; &psql->pelem[i - 1]; // 插入位置for (p &#61; &psql->pelem[psql->len - 1]; p >&#61; q; --p) {*(p &#43; 1) &#61; *q; // 插入位置及之后的元素后移}*q &#61; elem;&#43;&#43;psql->len;return OK;
}/* 将两个顺序表合并到另一个顺序表中 */
void merge_sq_list(SqList *psqla, SqList *psqlb, SqList *psqlc)
{// 已知顺序线性表psqla&#xff0c;psqlb的元素按值非递减排列// 归并psqla, psqlb得到的新顺序线性表psqlc的元素也按值非递减排列ElemType *pa, *pb, *pc;ElemType *pa_last, *pb_last;if (!psqla || !psqlb || !psqla->pelem || !psqlb->pelem) return ;pa &#61; psqla->pelem;pb &#61; psqlb->pelem;psqlc->lsize &#61; psqlc->len &#61; psqla->len &#43; psqlb->len;pc &#61; psqlc->pelem &#61; (ElemType *)malloc(psqlc->lsize * sizeof(ElemType));if (!pc) exit(MALLOCFAILE);pa_last &#61; psqla->pelem &#43; psqla->len - 1;pb_last &#61; psqlb->pelem &#43; psqlb->len - 1;while (pa <&#61; pa_last && pb <&#61; pb_last) {if (*pa <&#61; *pb) *pc&#43;&#43; &#61; *pa&#43;&#43;;else *pc&#43;&#43; &#61; *pb&#43;&#43;;}while (pa <&#61; pa_last) *pc&#43;&#43; &#61; *pa&#43;&#43;;while (pb <&#61; pb_last) *pc&#43;&#43; &#61; *pb&#43;&#43;;
}/* 简单测试以上各个函数 */
int main(void)
{int i, rv;ElemType elem;SqList psqla, psqlb, psqlc;i &#61; 1;elem &#61; 1;// 创建顺序线性表空间if ((rv &#61; malloc_sq_list(&psqla)) !&#61; OK || \(rv &#61; malloc_sq_list(&psqlb)) !&#61; OK ) {fprintf(stderr, "Create sequence list failed\n");exit(FAILE);}// 往顺序线性表中插入值insert_elem2sq_list(&psqla, i&#43;&#43;, elem&#43;&#43;);insert_elem2sq_list(&psqlb, i, elem);printf("%d %d\n", *psqla.pelem, psqlb.pelem[--i]);// 合并两个线性表merge_sq_list(&psqla, &psqlb, &psqlc);printf("%d %d\n", *psqlc.pelem, psqlc.pelem[i]);// 释放顺序线性表free_sq_list(&psqla);free_sq_list(&psqlb);free_sq_list(&psqlc);return 0;
}

06.15
-man realloc-
原型。void *realloc(void *ptr, size_t size);
功能。realloc函数将ptr所指向的内存块的大小改为size字节大小&#xff08;原内容不会被改变&#xff09;。如果新的大小大于原来的大小&#xff0c;新增的内存块不会被初始化。如果ptr为NULL&#xff0c;那么realloc相当于malloc&#xff08;size&#xff09;&#xff1b;如果size等于0并且ptr不为NULL&#xff0c;则该调用相当于free(ptr)。除非ptr为NULL&#xff0c;否则ptr必须是之前malloc()&#xff0c;calloc()或realloc()的返回值。如果指向的区域被移动&#xff0c;则原来的内存区域会被自动的free(ptr)。
返回值。realloc()函数返回一个指向新内存区域的指针&#xff0c;若请求失败则返回NULL。如果size等于0&#xff0c;NULL或者传递给free()函数过后的指针将被返回。如果realloc()失败&#xff0c;则原来的内存块将不变&#xff1b;它不会被释放或移除。

[2] 算法复杂度分析
insert_elem2sq_list具有重复&#xff08;循环&#xff09;的是元素的移动操作&#xff0c;最坏的情况是将元素插入到表中的第一个元素之前&#xff08;需要移动n个元素 – 假设表具有n个元素&#xff09;。insert_elem2sq_list的复杂度可用O(n)来表示。同理&#xff0c;合并俩链表的操作的时间复杂度也为O(n)。[《CSAPP》中有更细致的分析]

线性表的特点是逻辑关系相邻的两个数据元素在内存中存储位置也是相邻关系&#xff0c;因此可以用一个简单的、直观的公式来表示&#xff08;在C语言中也能够用简单的方式访问&#xff0c;如下标、偏移&#xff09;。然而这种存储结构也有一个弱点&#xff1a;在作插入或删除操作时&#xff0c;需要移动大量元素。


2.2 链表


(1) 线性链表

线性链表。线性链表的存储结构特点是各个逻辑关系相邻的数据元素既可以用连续的内存单元存储也可以用非连续的内存单元存储。[见链表的结点 —— 因为每个结点中只含有一个指针域&#xff0c;故而称这样的链表为线性链表或单链表]

链表的结点。为了表示线性链表中ai与ai&#43;1元素之间的逻辑关系&#xff08;ai&#43;1为ai的后继元素&#xff09;&#xff0c;ai除了要存储本身的信息外&#xff0c;还要存储ai&#43;1的地址信息&#xff08;指针域&#xff09;&#xff0c;ai中的这两部分信息被称为结点。

例 – 用C语言实现一个简单的单链表
06.17
[1] 代码简单实现
single_link_list.c

/* signle_link_list.c* 单链表线性表的简单表示和实现* 2016.06.15 - 06.17*/
#include <stdlib.h>
#include <stdio.h>/* 函数返回值 */
#define NK -1 // 函数未正常返回
#define OK 0 // 函数正常返回
#define NP 1 // 函数参数不合法
#define ME 2 // 空间分配失败/* 描述单链表的结构体类型 */
typedef char ElemType;
typedef struct _single_link_list_node {ElemType data; // 数据域struct _single_link_list_node *next; // 指针域
}SLNode, SLHead;/* 创建一个包含n个结点的单链表&#xff0c;每个结点的数据域为创建时结点的顺序 */
SLHead *create_single_link_list(unsigned n)
{unsigned i;SLHead *head;SLNode *pcn, *pln;i &#61; 0;if (n < 1) return NULL;// 头结点if (NULL &#61;&#61; (head &#61; (SLNode *)malloc(sizeof(SLNode)))) {fprintf(stderr, "head of link list malloc failed\n");exit(ME); // 退出本进程&#xff0c;进程用户空间被回收从而堆空间自然被回收}head->data &#61; 0;head->next &#61; NULL;pln &#61; head;// 单链表中的结点while (n--) {if (NULL &#61;&#61; (pcn &#61; (SLNode *)malloc(sizeof(SLNode)))) {fprintf(stderr, "%d th node malloc failed\n", &#43;&#43;i);exit(ME);}pcn->next &#61; NULL;pcn->data &#61; &#43;&#43;i;pln->next &#61; pcn;pln &#61; pcn;}return head;
}/* 释放具有n个结点的单链表 */
void free_single_link_list(SLHead *head)
{SLNode *pcn, *pnn;pcn &#61; pnn &#61; head;while (pcn) {pnn &#61; pnn->next;free(pcn);pcn &#61; pnn;}
}/* 往单链表中的第i个结点前插入一个元素 */
int insert_node2link_list(SLHead *head, unsigned i, ElemType e)
{int j;SLNode *pcn, *pnewn;if (!head) return NP;j &#61; 0;pcn &#61; head;while (pcn && j < i - 1) { // 寻找i - 1个结点pcn &#61; pcn->next;&#43;&#43;j;}if (!pcn || j > i - 1) return NK;if ((pnewn &#61; (SLNode *)malloc(sizeof(SLNode))) &#61;&#61; NULL) {fprintf(stderr, "insert %d element failed\n", e);return NK;}pnewn->data &#61; e;pnewn->next &#61; pcn->next;pcn->next &#61; pnewn;return OK;
}/* 合并两个单链表 */
/* 已知两个单链表元素按值非减排列 */
/* 归并两个链表得到新链表&#xff0c;新链表也按照值非递减排列 */
SLHead *merge_link_list(SLHead *heada, SLHead *headb)
{SLNode *la, *lb, *lc, *headc;if (!heada || !headb) return ;la &#61; heada->next;lb &#61; headb->next;headc &#61; lc &#61; heada;while (la && lb) {if (la->data <&#61; lb->data) {lc->next &#61; la;lc &#61; la;la &#61; la->next;} else {lc->next &#61; lb;lc &#61; lb;lb &#61; lb->next;}}lc->next &#61; la ? la : lb;free(headb);return headc;
}/* 输出单链表的所有元素 */
void print_link_list_node_value(SLHead *head)
{SLNode *p;if (!head) return;p &#61; head->next;while (p) {printf("%d ", p->data);p &#61; p->next;}printf("\n");
}/* 简单测试单链表 */
int main(void)
{int i;SLHead *ha, *hb, *hc;unsigned la_len, lb_len;la_len &#61; lb_len &#61; 7;if (NULL !&#61; (ha &#61; create_single_link_list(la_len)))print_link_list_node_value(ha);if (NULL !&#61; (hb &#61; create_single_link_list(lb_len)))print_link_list_node_value(hb);hc &#61; merge_link_list(ha, hb);print_link_list_node_value(hc);for (i &#61; 1; i < 15; &#43;&#43;i)insert_node2link_list(hc, i, i);print_link_list_node_value(hc);free_single_link_list(hc);return 0;
}

在shell下编译并运行single_link_list.c得以下结果&#xff1a;
这里写图片描述

[2] 复杂度分析
同顺序表&#xff0c;单链表的插入操作的时间复杂度为O(n)。合并单链表的时间复杂度也为O(n)。


(2) 循环链表

循环链表。循环链表的最后一个数据元素指向第一个数据元素&#xff08;其他同线性链表&#xff09;。


(3) 双向链表

双向链表。双向链表的结点中有两个指针域&#xff0c;该结点中的一个指针域指向后驱元素&#xff0c;一个指针域指向前趋元素。

例 — 用C语言实现一个简单的双向链表
06.22
double_link_list.c

/* double_link_list.c* 双向链表的简单描述* 2016.06.17 - 06.22*/
#include <stdio.h>
#include <stdlib.h>/* 函数返回值 */
#define NK -1 // 函数非正常返回
#define OK 0 // 函数正常返回
#define EP 1 // 参数不合法typedef char ElemType; // 双向链表中数据域中的数据类型
/* 描述双向链表的结构体 */
typedef struct _DulNode {ElemType dt;struct _DulNode *pr;struct _DulNode *pn;unsigned nm;
}DulNode, *DuLinkList;/* 创建双向链表 */
/* 结点中的数据域的值为结点被创建时的个数 */
DuLinkList create_dul_link_list(unsigned n)
{int i;DuLinkList head, ps, nt;if (NULL &#61;&#61; (ps &#61; (DulNode *)malloc(sizeof(DulNode)))) {exit(NK);}i &#61; 1;ps->pr &#61; NULL;ps->pn &#61; NULL;ps->dt &#61; i;head &#61; ps;ps->nm &#61; i;while (--n) {if (NULL &#61;&#61; (nt &#61; (DulNode *)malloc(sizeof(DulNode)))) {exit(NK);}ps->pn &#61; nt;nt->pr &#61; ps;nt->dt &#61; &#43;&#43;i;ps &#61; nt;head->nm&#43;&#43;;}ps->pn &#61; head;head->pr &#61; ps;return head;
}
/* 释放双向链表 */
void free_dul_link_list(DuLinkList dl)
{int i;unsigned n;DuLinkList pr, pn;if (!dl) return;n &#61; dl->nm;pr &#61; dl;pn &#61; dl->pn;for (i &#61; 1; i <&#61; n; &#43;&#43;i) {if (pr) {free(pr);pr &#61; pn;pn &#61; pn->pn;}}
}
/* 合并俩双向链表 */
DuLinkList merge_dul_link_list(DuLinkList dla, DuLinkList dlb)
{// 已知双向链表dla和dlb按值递增排列// 将dla和dlb合并成一个双向链表&#xff08;递增排列&#xff09;unsigned dla_nm, dlb_nm;DuLinkList dlc, head, tail;if (!dla || !dlb) return NULL;dla_nm &#61; dla->nm;dlb_nm &#61; dlb->nm;if (dla->dt <&#61; dlb->dt) {dlc &#61; head &#61; dla;dla &#61; dla->pn;dla_nm--;} else {dlc &#61; head &#61; dlb;dlb &#61; dlb->pn;dlb_nm--;}head->nm &#61; dla_nm &#43; dlb_nm &#43; 1;while (dla_nm && dlb_nm) {if (dla->dt <&#61; dlb->dt) {dlc->pn &#61; dla;dla->pr &#61; dlc;dlc &#61; dla;dla &#61; dla->pn;dla_nm--;} else {dlc->pn &#61; dlb;dlb->pr &#61; dlc;dlc &#61; dlb;dlb &#61; dlb->pn;dlb_nm--;}}tail &#61; dla_nm ? dla : dlb;dlc->pn &#61; tail;tail->pr &#61; dlc;dlc &#61; tail;dlc->pn &#61; head;head->pr &#61; dlc;return head;
}/* 打印双向链表中的内容 - 验证 */
void print_dul_node_value(DuLinkList dl)
{unsigned i, n;if (!dl) return ;i &#61; 1;n &#61; dl->nm;for (i &#61; 1; i <&#61; n; &#43;&#43;i) {printf("%d ", dl->dt);dl &#61; dl->pn;}printf("\n");
}/* 简单测试双向链表 */
int main(void)
{unsigned dl_len;DuLinkList dla, dlb, dlc;dl_len &#61; 7;dla &#61; create_dul_link_list(dl_len);dlb &#61; create_dul_link_list(dl_len);print_dul_node_value(dla);print_dul_node_value(dlb);dlc &#61; merge_dul_link_list(dla, dlb);print_dul_node_value(dlc);//free_dul_link_list(dlc);return 0;
}

运行double_link_list.c得以下结果&#xff1a;
这里写图片描述


2.3 一元多项式的表示及相加

06.23
这里写图片描述


3 栈和队列


3.1 栈及栈的简单应用

。栈是限定仅在表尾进行插入或删除操作的线性表。表尾端称为栈顶&#xff0c;表头端称为栈底。顺序栈即利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素&#xff0c;同时设置一个指向栈顶元素的指针。[链栈的各个数据元素的存储单元不一定连续]


(1) 顺序栈

例 – 用C实现一个简单的顺序栈

06.23
一般来说&#xff0c;在初始化设空栈时不应限定栈的最大容量。一个较合理的做法是&#xff1a;先为栈分配一个基本容量&#xff0c;然后在应用过程中&#xff0c;当栈的空间不够使用时在逐段扩大。

[1] 描述栈的结构体类型

/* 描述栈的结构体类型 */
typedef SElemType int;
typedef struct _SqStack{SElemType *base;SElemType *top;int stacksize;
}SqStack;

其中&#xff0c;stacksize指示栈的当前可使用的最大容量。栈的初始化操作为&#xff1a;按设定的初始分配量进行第一次分配&#xff0c;base为栈底指针&#xff0c;在顺序栈中&#xff0c;它始终指向栈底的位置&#xff0c;若base的值为NULL&#xff0c;则表明栈结构不存在。称top为栈顶指针&#xff0c;其初值指向栈底&#xff0c;即top&#61;base可作为栈空的标记&#xff0c;每当插入新的栈顶元素时&#xff0c;指针top增1&#xff1b;删除栈顶元素时&#xff0c;指针top减1&#xff0c;因此&#xff0c;非空栈中的栈顶指针始终在栈顶元素的下一个位置上。

[2] 跟栈相关的基本操作
06.26
stack_basic.c

/* stack_basic.c* 栈的简单描述与实现* 2016.06.23 - 06.26*/
#include <stdio.h>
#include <stdlib.h>#define STACK_INIT_SIZE 100 // 栈空间初始分配大小
#define STACKINCREMENT 10 // 栈空间分配增量
#define OK 0 // 函数正常返回
#define NK 11 // 函数非正常返回
#define NP 22 // 函数参数无效/* 描述栈的结构体类型 */
typedef int SElemType;
typedef struct _SqStack{SElemType *base;SElemType *top;int stacksize;
}SqStack;/* 基本操作 */
// 构造一个空栈 - 为栈分配空间&#xff0c;指向栈顶与栈底的变量都指向栈底
int init_stack(SqStack *stack)
{if (!stack) return NP;stack->base &#61; (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));if (!stack->base) return NK;stack->top &#61; stack->base;stack->stacksize &#61; STACK_INIT_SIZE;return OK;
}// 销毁栈 - 释放为栈分配的空间
void destroy_stack(SqStack *stack)
{if (!stack) return;if (stack->base) {stack->stacksize &#61; 0;free(stack->base);stack->base &#61; NULL;stack->top &#61; NULL;}
}// 将栈设为空栈 - 将指向栈顶的变量指向栈底
void clear_stack(SqStack *stack)
{if (!stack) return;if (stack->top && stack->base)stack->top &#61; stack->base;
}// 判断是否为空栈
int is_stack_empty(SqStack *stack)
{if (stack && stack->base && stack->top)return (stack->base &#61;&#61; stack->top);elsereturn NP;
}// 获取栈的长度
int get_stack_length(SqStack *stack)
{if (stack) return stack->stacksize;else return NP;
}// 获取栈顶元素
SElemType get_top(SqStack *stack)
{SElemType *top;if (stack && stack->top && stack->base && \stack->top !&#61; stack->base) {top &#61; stack->top - 1;return *top;}return NP;
}// 往栈顶中插入一个元素
int push(SqStack *stack, SElemType e)
{int status;SElemType *base;status &#61; is_stack_empty(stack);if (NP !&#61; status) {if (stack->top - stack->base < stack->stacksize) { // 栈未满*stack->top &#61; e;stack->top&#43;&#43;;return OK;} else { // 栈已满base &#61; (SElemType *)realloc(stack->base, (stack->stacksize &#43; STACKINCREMENT) * sizeof(SElemType));if (base) return (NK);stack->base &#61; base;stack->stacksize &#43;&#61; STACKINCREMENT;*stack->top &#61; e;stack->top&#43;&#43;;return OK;}}return NP;
}// 删除栈顶元素
int pop(SqStack *stack)
{int status;status &#61; is_stack_empty(stack);if (NP !&#61; status && !status) {stack->top--;return OK;}return NK;
}
// 遍历栈
void traverse_stack(SqStack *stack)
{int status;SElemType *pe;status &#61; is_stack_empty(stack);if (NP !&#61; status && !status) {pe &#61; stack->top - 1;while (pe - stack->base) {printf("%d ", *pe--); // int}printf("%d\n", *pe);}
}/* 简单测试栈 - 部分函数 */
int main(void)
{int i, rv;SqStack stack;if ((rv &#61; init_stack(&stack)) !&#61; OK) // 初始化栈exit(NK);for (i &#61; 0; i < STACK_INIT_SIZE; &#43;&#43;i) // 入栈push(&stack, i);traverse_stack(&stack); // 遍历栈destroy_stack(&stack); // 销毁栈return 0;
}

在shell中运行该程序&#xff0c;得到以下测试结果&#xff1a;
这里写图片描述


(2) 栈的简单应用

06.27
[还相差甚远]

[1] 数制转换
这里写图片描述

[2] 括号匹配的检验
这里写图片描述

[3] 行编辑程序
这里写图片描述

[4] 迷宫求解
这里写图片描述

[5] 表达式求值
这里写图片描述


3.2 栈与递归的实现

06.28
[…如汉诺塔、八皇后问题…]


3.3 队列

队列。队列是一种先进先出的线性表。它只允许在表的一端&#xff08;队尾&#xff09;进行插入&#xff0c;而在另一端&#xff08;队头&#xff09;删除元素。
这里写图片描述


(1) 链队列

!例 – 用C语言实现一个简单的链队列程序


(2) 循环队列

这里写图片描述


3.4 离散事件模拟

[..银行业务模拟程序..]

06.09


4 串


4.1 串的基本操作

&#xff08;字符串&#xff09;。串是由零个或多个字符组成的有限序列。

串定长顺序存储表示。用一组地址连续的内存单元存储串值的字符序列。

堆分配存储表示。仍以一组地址连续的内存单元存储串值的字符序列&#xff0c;但它们的存储空间是在程序执行过程中动态分配的。

串的块链存储表示。以结点方式存储各个串。

06.30
例 – 用C语言编写一个简单的关于串&#xff08;顺序存储方式&#xff09;的程序。&#xff08;串比较、串连接、求串长度、串模式匹配等&#xff09;[串相关的操作无须涉及任何与内核交互&#xff0c;《TCPL》等书涉及关于串函数的一些编写内容&#xff0c;本书中的模式匹配算法可以值得&#xff08;因为没怎么看过&#xff09;一看]。


4.2 串的简单应用

06.29


(1) 文本编辑

这里写图片描述


(2) 建立词索引表

信息检索主要操作。在大量存放的磁盘上的信息中查询一个特定的信息&#xff08;为了提高查询效率&#xff0c;一个重要的问题就是建立一个好的索引系统&#xff09;。
这里写图片描述

[2016.06.12 - 10:15]


推荐阅读
  • 本文介绍了使用PHP实现断点续传乱序合并文件的方法和源码。由于网络原因,文件需要分割成多个部分发送,因此无法按顺序接收。文章中提供了merge2.php的源码,通过使用shuffle函数打乱文件读取顺序,实现了乱序合并文件的功能。同时,还介绍了filesize、glob、unlink、fopen等相关函数的使用。阅读本文可以了解如何使用PHP实现断点续传乱序合并文件的具体步骤。 ... [详细]
  • 本文介绍了在mac环境下使用nginx配置nodejs代理服务器的步骤,包括安装nginx、创建目录和文件、配置代理的域名和日志记录等。 ... [详细]
  • STL迭代器的种类及其功能介绍
    本文介绍了标准模板库(STL)定义的五种迭代器的种类和功能。通过图表展示了这几种迭代器之间的关系,并详细描述了各个迭代器的功能和使用方法。其中,输入迭代器用于从容器中读取元素,输出迭代器用于向容器中写入元素,正向迭代器是输入迭代器和输出迭代器的组合。本文的目的是帮助读者更好地理解STL迭代器的使用方法和特点。 ... [详细]
  • linux进阶50——无锁CAS
    1.概念比较并交换(compareandswap,CAS),是原⼦操作的⼀种,可⽤于在多线程编程中实现不被打断的数据交换操作࿰ ... [详细]
  • vue使用
    关键词: ... [详细]
  • 学习SLAM的女生,很酷
    本文介绍了学习SLAM的女生的故事,她们选择SLAM作为研究方向,面临各种学习挑战,但坚持不懈,最终获得成功。文章鼓励未来想走科研道路的女生勇敢追求自己的梦想,同时提到了一位正在英国攻读硕士学位的女生与SLAM结缘的经历。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文介绍了C++中省略号类型和参数个数不确定函数参数的使用方法,并提供了一个范例。通过宏定义的方式,可以方便地处理不定参数的情况。文章中给出了具体的代码实现,并对代码进行了解释和说明。这对于需要处理不定参数的情况的程序员来说,是一个很有用的参考资料。 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 解决Cydia数据库错误:could not open file /var/lib/dpkg/status 的方法
    本文介绍了解决iOS系统中Cydia数据库错误的方法。通过使用苹果电脑上的Impactor工具和NewTerm软件,以及ifunbox工具和终端命令,可以解决该问题。具体步骤包括下载所需工具、连接手机到电脑、安装NewTerm、下载ifunbox并注册Dropbox账号、下载并解压lib.zip文件、将lib文件夹拖入Books文件夹中,并将lib文件夹拷贝到/var/目录下。以上方法适用于已经越狱且出现Cydia数据库错误的iPhone手机。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了Linux Shell中括号和整数扩展的使用方法,包括命令组、命令替换、初始化数组以及算术表达式和逻辑判断的相关内容。括号中的命令将会在新开的子shell中顺序执行,括号中的变量不能被脚本余下的部分使用。命令替换可以用于将命令的标准输出作为另一个命令的输入。括号中的运算符和表达式符合C语言运算规则,可以用在整数扩展中进行算术计算和逻辑判断。 ... [详细]
  • 十大经典排序算法动图演示+Python实现
    本文介绍了十大经典排序算法的原理、演示和Python实现。排序算法分为内部排序和外部排序,常见的内部排序算法有插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。文章还解释了时间复杂度和稳定性的概念,并提供了相关的名词解释。 ... [详细]
  • Python脚本编写创建输出数据库并添加模型和场数据的方法
    本文介绍了使用Python脚本编写创建输出数据库并添加模型数据和场数据的方法。首先导入相应模块,然后创建输出数据库并添加材料属性、截面、部件实例、分析步和帧、节点和单元等对象。接着向输出数据库中添加场数据和历程数据,本例中只添加了节点位移。最后保存数据库文件并关闭文件。文章还提供了部分代码和Abaqus操作步骤。另外,作者还建立了关于Abaqus的学习交流群,欢迎加入并提问。 ... [详细]
author-avatar
丿车荣璇
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有