线性表
定义
- 由同类型数据元素构成有序序列的线性结构
- 表中元素个数为线性表的长度
- 无元素,称空表
- 起始位置:表头, 结束位置:表尾
抽象数据类型描述
- 类型名称:线性表(list)
- 抽象数据类型:数据对象、操作集
- 数据对象集:线性表的数据对象集合为{a1,a2,…,an},每个元素的类型均为DataType。其中,除了第一个元素a1外,每一个元素有且只有一个直接前驱元素,除最后一个元素an外,每一个元素有且只有一个直接后继元素。数据元素之间的关系是一对一的关系。
- 操作集:线性表基本操作主要有:
- Operation
- InitList(*L):初始化操作,建立一个空的线性表。
- ListEmpty(L):若线性表为空,返回true,否则返回false。
- ClearList(*L):线性表清空。
- GetElem(L,i,*e):将线性表L中第i个位置元素返回给e。
- LocateElem(L,e):在线性表L中查找与给定值e相等的元素,如果查找成功,返回该元素在表中的序列号;否则,返回0表示失败。
- ListInsert(*L,i,e):在线性表的第i个位置插入元素e。
- ListDelete(*L,i,*e):删除线性表L中的第i个元素,并用e返回其值
- ListLength(L):返回线性表L的元素个数。
- PrintList(L):打印线性表
线性表顺序存储
- 所谓顺序表就是顺序存储的线性表。顺序存储是用一组地址连续的存储单元依次存放线性表中各个元素的存储结构
- 特点
- 在线性表中逻辑上相邻的数据元素,在物理存储上也是相邻的
- 存储密度高,但要预先分配“足够应用”的存储空间,这可能会造成存储空间的浪费
- 便于随机存储
- 不便于插入和删除操作,这是因为在顺序表上进行的插入和删除操作会引起大量数据元素的移动
#include<iostream> using namespace std; const int MaxSize = 100; class list { public: list() { length = 0; } list(int a[], int n); int Length(); void Insert(int i,int x); int Delete(int i); void listprint(); int Location(int x); private: int length; int data[MaxSize]; }; list::list(int a[],int n) { for (int i = 0; i<n; i++) data[i] = a[i]; this->length = n; } int list::Length() { return this->length; } void list::Insert(int i, int x) { if (length > MaxSize) throw "上溢"; if (i<1||i>length+1) throw "非法插入"; for (int j = length;j>=i;j--) { data[j] = data[j - 1]; } data[i - 1] = x; length++; } int list::Delete(int i) { if (length > MaxSize) throw "上溢"; if (i<1 || i>length + 1) throw "非法删除"; int x = data[i - 1]; for (int j=i;j<length;j++) { data[j - 1] = data[j]; } length--; return x; } void list::listprint() { for (int i=0;i<length;i++) { cout << data[i] << ' '; } cout << endl; } int list::Location(int x) { for (int i = 0; i < length; i++) { if (data[i]==x) { return i + 1; } } return 0; } int main() { list p; p.Insert(1, 5); p.Insert(2, 9); //p.PrintList(); p.Insert(2, 3); p.listprint(); //cout << p.Length() << endl; //p.listprint(); cout << p.Delete(2) << endl; p.listprint(); getchar(); return 0; }
线性表链式存储
-
概念:
- 链式存储结构,结点在存储器中的位置是任意的,即逻辑上相邻的数据元素在物理上不一定相邻;与上面提到的顺序存储不同,链式存储在计算机内存中的表示是随机的,它只是在逻辑是相邻的,物理是不相邻;线性表的链式表示又称为非顺序映像或链式映像;链表是通过指针来进行实现的
- 在插入、删除不需要移动数据元素,只需要修改‘链’
-
链表是通过每个结点连接在一起来实现的,所以每个结点都由两个域组成。
- 数据域:存储元素数值数据;
- 指针域:存储直接后继结点的存储位置;
-
所以由许多个结点组成的表就叫链表。
-
链表中还有头指针,头结点,首元结点:
- 头指针是指向链表中第一个结点的指针,
- 首元结点是指链表中存储第一个数据元素a1的结点,
- 头结点是在链表的首元结点之前附设的一个结点;
-
数据域内只放空表标志和表长等信息。
-
链表的分类:
- 结点只有一个指针域的链表,称为单链表或线性链表;
- 有两个指针域的链表,称为双链表;
- 首尾相接的链表称为循环链表;
-
单链表
- 概念:单链表是由表头唯一确定,因此单链表可以用头指针的名字来命名
- 若头指针名是L,则把链表称为表L
#include<iostream> using namespace std; class Node { public: Node(int x) { data = x; next = NULL; } int data; Node *next; }; class linklist { public: linklist() { head = new Node(0); } void Insert(int x, int pos); int Length(); void createlist(int x); void printlist(); int delete_pos(int pos); private: Node *head; }; void linklist::createlist(int x) { Node *p = head; Node *s = new Node(x); s->next = p->next; p->next = s; } void linklist::Insert(int x, int pos) { /* if (head==NULL) { head->data=x; head->next = NULL; }*/ Node *p = head; Node *s = new Node(x); int count = 0; while (p!=NULL) { if (count==pos-1) { s->next = p->next; p->next = s; } p = p->next; count++; } } int linklist::Length() { int length=0; Node *p = head; while (p!=NULL) { p = p->next; length++; } return length; } void linklist::printlist() { Node *p = head; while (p!=NULL) { cout << p->data; cout << " "; p = p->next; } cout << endl; } int linklist::delete_pos(int pos) { Node *p = head; int count = 0; while (p != NULL) { if (count == pos - 1) { Node *s = p->next; int x = s->data; p->next = s->next; delete s; return x; } p = p->next; count++; } return -1; } int main() { linklist l; int arry[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; for (int i = 9; i >= 0; i--) l.createlist(arry[i]); l.Insert(5, 2); l.printlist(); cout << l.Length() << endl; l.delete_pos(2); l.printlist(); cout << l.Length() << endl; //cout << l.Length() << endl; system("pause"); }