算法与数据结构(1)--线性表
线性表是最基本、最简单、也是最常用的一种数据结构。线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的。线性表的逻辑结构简单,便于实现和操作。因此,线性表这种数据结构在实际应用中是广泛采用的一种数据结构。
1结构
线性表是一种常用的数据结构,以下介绍线性表及其顺序存储,并对栈和队列及它们的顺序实现给出了详细的设计描述。
在实际应用中,线性表都是以栈、队列、字符串等特殊线性表的形式来使用的。由于这些特殊线性表都具有各自的特性,因此,掌握这些特殊线性表的特性,对于数据运算的可靠性和提高操作效率都是至关重要的。
线性表是一个线性结构,它是一个含有n≥0个结点的有限序列,对于其中的结点,有且仅有一个开始结点没有前驱但有一个后继结点,有且仅有一个终端结点没有后继但有一个前驱结点,其它的结点都有且仅有一个前驱和一个后继结点。一般地,一个线性表可以表示成一个线性序列:k1,k2,…,kn,其中k1是开始结点,kn是终端结点。
是一个数据元素的有序(次序)集
2特征
线性结构的基本特征为:
1.集合中必存在唯一的一个“第一元素”;
2.集合中必存在唯一的一个 “最后元素” ;
3.除最后一个元素之外,均有 唯一的后继(后件);
4.除第一个元素之外,均有 唯一的前驱(前件)。
由n(n≥0)个数据元素(结点)a1,a2,…,an组成的有限序列。
数据元素的个数n定义为表的长度。
当n=0时称为空表。
常常将非空的线性表(n>0)记作:
(a1,a2,…an)
数据元素ai(1≦i≦n)只是一个抽象的符号,其具体含义在不同的情况下可以不同。
线性表的基本操作
1) MakeEmpty(L) 这是一个将L变为空表的方法
2) Length(L) 返回表L的长度,即表中元素个数
3) Get(L,i) 这是一个函数,函数值为L中位置i处的元素(1≤i≤n)
4) Prev(L,i) 取i的前驱元素
5) Next(L,i) 取i的后继元素
6) Locate(L,x) 这是一个函数,函数值为元素x在L中的位置
7) Insert(L,i,x)在表L的位置i处插入元素x,将原占据位置i的元素及后面的元素都向后推一个位置
8) Delete(L,p) 从表L中删除位置p处的元素
9) IsEmpty(L) 如果表L为空表(长度为0)则返回true,否则返回false
10) Clear(L)清除所有元素
11) Init(L)同第一个,初始化线性表为空
12) Traverse(L)遍历输出所有元素
13) Find(L,x)查找并返回元素
14) Update(L,x)修改元素
15) Sort(L)对所有元素重新按给定的条件排序
16) strstr(string1,string2)用于字符数组的求string1中出现string2的首地址
回顾代码如下
#include "stdio.h" //线性表的顺序存储结构 #define MAXSIZE 100 #define TRUE 1 #define FALSE 0 typedef struct { int data[MAXSIZE]; int last; }SeqList; // 序表的初始化 SeqList SeqListInit() {// 构造一个空的线性表L SeqList L; //定义L为顺序表 L.last = 0; //顺序表长度为零 return L; //返回空顺序表 } // 元素定位 int SeqListLocate(SeqList L, int x) {// 在顺序表L中查找值为x的元素。若查找成功,则返回它在顺序表中的位序,否则返回-1表示查找失败 int i = 1; while(i <= L.last && L.data[i - 1] != x) { i++; } if (i <= L.last) { return i; // 返回数据元素的位序 } else { return 0; // 查找失败 } } // 线性表判空 int IsEmpty(SeqList L) { return (L.last == 0 ? TRUE : FALSE); } // 插入运算 SeqList SeqListInsert(SeqList L, int i, int x) {// 在顺序表中的第i个位置插入元素x int j; if(L.last == MAXSIZE) { printf("表满\n"); // 表满,退出 exit(0); } if(i < 1 || i > L.last + 1) { printf("插入位置错误\n"); // 插入位置错,退出 exit(0); } for(j = L.last - 1; j >= i - 1; j--) { L.data[j + 1] = L.data[j]; // 第i个位置后的数组元素逐一后移 } L.data[i - 1] = x; // 新元素插入到第i个位置 L.last++; // 顺序表长度增1 return (L); // 返回插入元素后的顺序表 } // 删除运算 SeqList SeqListDelete(SeqList L, int i) {// 删除顺序表中的第i个元素 int j; if (i < 1 || i > L.last) { printf("位置非法\n"); // 检查空表及删除位置的合法性 exit(0); } for(j = i; j <= L.last - 1; j++) { L.data[j - 1] = L.data[j]; // 向上移动 } L.last--; // 顺序表长度减1 return (L); // 返回删除元素后的顺序表 } // 合并非递减有序顺序表 SeqList SeqListMerge(SeqList Sla, SeqList Slb) {// 将非递减有序的顺序表Sla和Slb合并成一个新的顺序表Slc,Slc也是非递减有序的 // 初始化 SeqList Slc; Slc.last = 0; int i = 0, j = 0, k = -1; while(i < Sla.last && j < Slb.last) // Sla和Slb均非空 { if(Sla.data[i] <= Slb.data[j]) { Slc.data[++k] = Sla.data[i++]; // Sla中元素插入Slc } else { Slc.data[++k] = Slb.data[j++]; // Slb中元素插入Slc } } while(i < Sla.last) { Slc.data[++k] = Sla.data[i++]; // Slb已空,将Sla表的剩余部分复制到新表 } while(j < Slb.last) { Slc.data[++k] = Slb.data[j++]; // Sla已空,将Slb表的剩余部分复制到新表 } Slc.last = k + 1; return (Slc); } // 展示SeqList的内容 void ShowData(SeqList L) { int i = 0; for (; i < L.last; ++i) { printf("%d\t", L.data[i]); } printf("\n"); } int main() { // 测试代码 SeqList l = SeqListInit(); l = SeqListInsert(l, 1, 20); l = SeqListInsert(l, 1, 13); l = SeqListInsert(l, 1, 10); ShowData(l); printf("L.last = %d\n", l.last); int x = SeqListLocate(l, 10); printf("10 in %d\n", x); l = SeqListDelete(l, 2); ShowData(l); SeqList l2 = SeqListInit(); l2 = SeqListInsert(l2, 1, 44); l2 = SeqListInsert(l2, 1, 23); l2 = SeqListInsert(l2, 1, 4); ShowData(l2); l = SeqListMerge(l, l2); ShowData(l); return 0; }
这其实是昨天回顾的,今天早上才有时间发篇博客~~