线性表介绍
来源:互联网 发布:淘宝店标制作网站 编辑:程序博客网 时间:2024/06/03 20:09
线性表是一种常用的数据结构。在实际应用中,线性表都是以栈、队列、字符串、数组等特殊线性表的形式来使用的。由于这些特殊线性表都具有各自的特性,因此,掌握这些特殊线性表的特性,对于数据运算的可靠性和提高操作效率都是至关重要的。
线性表是一个线性结构,它是一个含有n≥0个结点的有限序列,对于其中的结点,有且仅有一个开始结点没有前驱但有一个后继结点,有且仅有一个终端结点没有后继但有一个前驱结点,其它的结点都有且仅有一个前驱和一个后继结点。
线性表分为顺序存储和链式存储。
这里主要简单介绍一下顺序存储,其特点是可以随机地访问元素,缺点是在进行插入和删除操作时需要移动大量的元素。
C语言实现代码:
/*Introduction:easy data structure of listDate:2017-03-26 */ #include <stdio.h> #include <stdlib.h> //宏定义 #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 //infeasible意为不可执行的 #define OVERFLOW -2 //代表溢出 #define LIST_INIT_SIZE 100 //线性表初始空间分配量 #define LISTINCREMENT 10 //线性表空间分配的增量 typedef int Status; typedef int ElemType; typedef struct LNode{ ElemType *elem; //存储空间的基地址 int length; //当前的长度 int listsize; //当前分配的存储容量 }SqList; /** *构造空的线性表 */ Status initList(SqList &L, int size){ if (size == 0) size = LIST_INIT_SIZE; L.elem = (ElemType *)malloc(size * sizeof(ElemType)); if(!L.elem) exit(OVERFLOW); //分配存储空间失败 L.length = 0; //初始空表长度为0 L.listsize = size ;//初始存储容量为100 return OK; } /************************************************************************/ /* 在第i位置插入e */ /************************************************************************/ Status insertList(SqList &L, ElemType e, int i){ ElemType *p, *q; if(i<0 ||i > L.length) return ERROR; //i值不合法 if (L.length >= L.listsize) { ElemType *newbase = (ElemType *)realloc(L.elem ,(L.listsize +LISTINCREMENT)*sizeof(ElemType)); if(!newbase) return OVERFLOW; //存储分配失败 L.elem = newbase; //新基值 L.listsize += LISTINCREMENT; //增加存储容量 } q = &L.elem[i]; //q为插入的位置 for (p = &L.elem[L.length]; p>=q; --p) { *p = *(p-1); //i元素之后的元素往后移动 } *q = e; //插入e L.length +=1; return OK; } /************************************************************************/ /* 删除第i位置元素,并用e返回其值 */ /************************************************************************/ Status deleteListElem(SqList &L, int i, ElemType &e){ int *p, *q; if(i<0 ||i > L.length) return ERROR; //i值不合法 q = &L.elem[i]; //被删除元素的位置为i,L.elem就是数组名, e = *q; //被删除元素的值赋值给e for (p = q; p< (L.elem + L.length); p++){ //元素左移 *p = *(p+1); } --L.length; return OK; } /************************************************************************/ /* 快速排序 */ /************************************************************************/ int partition(SqList &L, ElemType low, ElemType high){ ElemType pivotkey = L.elem[low]; //枢轴记录关键字 while (low < high) { //从表的两端向中间扫描 while (low < high && L.elem[high] >= pivotkey ) --high;//高端位置扫描 L.elem[low] = L.elem[high]; //交换数据,小于pivotkey移到低端 L.elem[high] = pivotkey; while (low < high && L.elem[low] <= pivotkey ) ++low; //低端扫描 L.elem[high] = L.elem[low]; //交换数据 大于pivotkey移到高端 L.elem[low] = pivotkey; } return low; } void quickSort(SqList &L, ElemType low, ElemType high){ int pivot; if(low < high) { pivot = partition(L, low, high); quickSort(L, low, pivot -1); //低端子表排序 quickSort(L, pivot +1, high); //高端子表排序 } } /************************************************************************/ /* 合并两个线性表 */ /************************************************************************/ void mergeList(SqList La, SqList Lb, SqList &Lc){ ElemType *pa, *pb, *pc; Lc.listsize = La.length + Lb.length; initList(Lc, Lc.listsize); //初始化LC\pc = Lc.elem; Lc.length = Lc.listsize; pc = Lc.elem; pa = La.elem; pb = Lb.elem; while (pa <= &La.elem[La.length -1] && pb <= &Lb.elem[Lb.length -1]){ if (*pa <= *pb) *pc++ = *pa++; else *pc++ = *pb++; } while(pa <= &La.elem[La.length -1]) *pc++ = *pa++; //插入La的剩余元素 while(pb <= &Lb.elem[Lb.length -1]) *pc++ = *pb++; //插入Lb的剩余元素 } /************************************************************************/ /* 打印list */ /************************************************************************/ void printList(SqList L){ printf("当前值:"); for (int i =0; i<L.length;i++) { printf("%d ", *(L.elem+i)); // L.elem为首地址 } printf("\n"); } int main() { SqList La,Lb,Lc; ElemType e; int init,i; init = initList(La, LIST_INIT_SIZE); int data[6] = {5,3,6,2,7,4}; for (i=0; i<6;i++) { insertList(La, data[i], i); } printf("LA:\n"); printList(La); //测试删除 deleteListElem(La, 3, e ); printList(La); //测试插入 insertList(La, e, 3); printList(La); //实现快速排序并将结果打印 quickSort(La,0, La.length-1); printList(La); printf("LB:\n"); initList(Lb, LIST_INIT_SIZE); int Bdata[5] = {1,3,2,4,6}; for (i=0; i<5;i++) { insertList(Lb, Bdata[i], i); } //实现快速排序并将结果打印 quickSort(Lb,0, Lb.length-1); printList(Lb); //测试合并 mergeList(La, Lb, Lc); printf("合并之后:\n"); printList(Lc); return 0; }
在定义线性表时,我们可以定义一个结构体来标识线性表
typedef struct LNode{ ElemType *elem; //存储空间的基地址 int length; //当前的长度 int listsize; //当前分配的存储容量 }SqList;
其中,我们必须定义线性表第一个元素的存放位置,即整个线性表的首地址,还要定义线性表的最大容量listsize,最后用一个length来表示当前线性表中元素的数目即线性表的长度
再接着我们介绍一下线性表的链式存储,这样的优点是插入和删除元素时只要改变指针的指向即可,缺点是要访问一个元素时必须进行遍历,不能确切地知道元素的位置。
C语言实现代码:
/*Introduction:easy Data Structure of LinkListDate:2017-03-26 */ #include <stdio.h> #include "stdlib.h" #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define OVERFLOW -2 typedef int Status; typedef int ElemType; typedef struct LNode{ ElemType data; //数据域 struct LNode *next; //指向下一个元素的指针域 }LNode, *LinkList; /************************************************************************/ /* 初始化链表 */ /************************************************************************/ Status initList(LinkList &L){ /*单链表的初始化*/ L = (LinkList)malloc(sizeof(LNode)); //申请一个头节点 if(!L) exit(OVERFLOW); //申请空间失败 L->next=NULL; //建立一个带头节点的空链表 return OK; } /************************************************************************/ /* 创建链表 */ /************************************************************************/ void createList(LinkList L, int n){ /*单链表的初始化*/ if (!L) { initList(L); } ElemType data; LinkList p,q = L; printf("输入节点数据的个数%d:\n", n); for(int i = 0; i<n; i++) { scanf("%d",&data); p = (LinkList) malloc( sizeof(LNode)); //申请一个新节点 q->data = data; q->next=p; if(i==n-1){ //当到了最后的一个节点时一定要将其next指针置为NULL q->next=NULL;break; } q=p; } } /************************************************************************/ /* 在第i位置插入e */ /************************************************************************/ Status insertList(LinkList L, ElemType e, int i){ LinkList s, p = L; int j = 0; while (p && j<i){ //寻找i节点 p = p->next; j++; } if (!p ||j >i) return ERROR; s = (LinkList) malloc(sizeof(LNode)); //生成新节点 s->data = e; s->next = p->next; //插入L中 p->next = s; return OK; } /************************************************************************/ /* 删除第i位置元素,并用e返回其值 */ /************************************************************************/ Status deleteListElem(LinkList L, int i, ElemType *e){ LinkList p, q; int j = 0; p = L; while (p && j<i){ p = p->next; ++j; } if (!p->next || j>i) return ERROR; //删除的位置不对 q = p->next; p->next = q->next; *e = q->data; free(q); //释放节点 return OK; } /************************************************************************/ /* 插入排序 */ /************************************************************************/ /* 1、先在原链表中以第一个节点为一个有序链表,其余节点为待定节点。 2、从图12链表中取节点,到图11链表中定位插入。 3、上面图示虽说画了两条链表,其实只有一条链表。在排序中,实质只增加了一个用于指向剩下需要排序节点的头指针first罢了。 这一点请读者务必搞清楚,要不然就可能认为它和上面的选择排序法一样了。 */ LinkList InsertSort(LinkList L) { LinkList first; /*为原链表剩下用于直接插入排序的节点头指针*/ LinkList t; /*临时指针变量:插入节点*/ LinkList p; /*临时指针变量*/ LinkList q; /*临时指针变量*/ first = L->next; /*原链表剩下用于直接插入排序的节点链表:可根据图12来理解。*/ L->next = NULL; /*只含有一个节点的链表的有序链表:可根据图11来理解。*/ while (first != NULL) /*遍历剩下无序的链表*/ { /*注意:这里for语句就是体现直接插入排序思想的地方*/ for (t = first, q = L;q != NULL && q->data < t->data;p = q, q = q->next); /*无序节点在有序链表中找插入的位置*/ /*退出for循环,就是找到了插入的位置*/ /*注意:按道理来说,这句话可以放到下面注释了的那个位置也应该对的,但是就是不能。原因:你若理解了上面的第3条,就知道了。*/ first = first->next; /*无序链表中的节点离开,以便它插入到有序链表中。*/ if (q == L) /*插在第一个节点之前*/ { L = t; } else /*p是q的前驱*/ { p->next = t; } t->next = q; /*完成插入动作*/ /*first = first->next;*/ } return L;} /************************************************************************/ /* 合并两个线性表 */ /************************************************************************/ LinkList mergeList(LinkList &La, LinkList &Lb, LinkList &Lc){ LinkList Test; Test=La; while(La->next!=NULL){ La=La->next; } //先遍历链表La,使La的尾节点的指针指向Lb的头节点 La->next=Lb; Lc=Test; Lc=InsertSort(Lc); return Lc; } /************************************************************************/ /* 打印list */ /************************************************************************/ void printList(LinkList L){ printf("打印链表:"); LinkList p; p = L; while(p){ printf("%d ", p->data); p = p->next; } printf("\n"); } int main() { LinkList La,Lb,Lc; ElemType *e; int init,i; printf("La:\n"); initList(La); createList(La, 5); printf("创建La之后的各元素值:\n"); printList(La); insertList(La, 7, 3); printf("插入元素之后的各元素值:\n"); printList(La); deleteListElem(La, 3, e); printf("删除的元素为:%d\n",*e); printf("删除元素之后的各元素值:\n"); printList(La); //输出插入排序之后的表 La=InsertSort(La); printf("插入排序之后La的各元素值:\n"); printList(La); printf("\n\n"); printf("Lb:\n"); initList(Lb); createList(Lb, 4); printf("创建Lb之后的"); printList(Lb); //输出插入排序之后的表 Lb=InsertSort(Lb); printf("插入排序之后Lb的各元素值:\n"); printList(Lb); printf("\n\n"); printf("Lc:\n"); initList(Lc); //初始化一个空表 Lc=mergeList(La,Lb,Lc); printf("合并之后的表:\n"); printList(Lc); return 0;}
这里主要需要弄清楚插入排序的思想和链式存储指针域的指向问题。
1 0
- 线性表介绍
- 线性表的相关介绍
- 线性回归介绍之一
- 数据结构(9)线性表之循环链表介绍
- 线性表--线性存储
- 线性表 线性结构
- 物理地址和线性地址介绍
- 线性表
- 线性表
- 线性表
- 线性表
- 线性表
- 线性表
- 线性表
- 线性表
- 线性表
- 线性表
- 线性表
- Mycat概述
- B1038. 统计同成绩学生(20)
- 算法设计与应用基础-第五周
- 待解决:selenium 未能获取alert!记录,期待大家指导!
- 栈之顺序栈
- 线性表介绍
- UIControl介绍以及Target-Action机制
- Unity 游戏存档 PlayerPrefs类的用法
- Leetcode 62. Unique Paths
- 新创建的iOS项目Cocoapods导入AFNetworking报错:AFNetworking.framework/AFNetworking' does not contain bitcode. Yo
- Android DataBinding入门篇
- Git之忽略文件(ignore file)
- maven中的groupId和artifactId到底指的是什么?
- NodeMcu上手