一、基本概念
1、线性表:简称表,是n(n>=0)个具有相同类型的数据元素的有限序列,线性表中数据元素的个数称为线性表的长度。长度为零时称为空表。
2、线性表的顺序存储结构称为顺序表。
3、单链表:单链表是一组任意的存储单元存放线性表的位置,这组存储单元可以连续也可以不连续,甚至可以零散分布在内存中的任意位置。
下面着重介绍有关单链表的操作:
#include<iostream> using namespace std; const int maxsize = 10; // 定义单链表的结点 struct Node { int data; struct Node *next; }; // linklist 类的声明 class linklist { public: linklist(); // 建立只有头结点的单链表 linklist(int a[],int n); // 建立有N个元素的单链表 ~linklist(); // 析构函数 void insert(int i,int x); // 在单链表的第 i 个位置插入元素值为 x 的结点 int Delete(int i); // 在单链表中删除第 i 个结点 int locate(int x); // 在单链表中 按值 查找 元素为x的元素 的位置(序号) void printlist(); // 按序号依次输出各元素 private : Node *first; // 单链表的头指针。 }; linklist::linklist() { first = new Node; // 生成头结点 first ->next=NULL; // 头结点指针域 置空 } linklist::linklist(int a[],int n) { Node *r,*s; first = new Node; // 生成头结点 r = first; // 尾指针 初始化 for(int i = 0;i<n;i++) { s=new Node; s->data= a[i]; // 为每个元素建立一个结点 r->next= s;r=s; // 将结点s插入到终端结点之后 } r->next = NULL; // 将终端指针域置空 } linklist::~linklist() { Node *q = NULL; while(first!=NULL) { q = first; first = first->next; delete q; } } void linklist::insert(int i,int x) { Node *p = first,*s = NULL; // 工作指针p指向头结点 int count = 0; while(p!=NULL&&count<i-1) // 查找第 i - 1个结点 { p = p->next; count++; } if(p==NULL) throw "位置"; // 将结点s 插入到p所指的i - 1 之后 else{ s= new Node;s->data= x; s->next=p->next; p->next = s; } } int linklist::Delete(int i) { Node *p = first,*q=NULL; int x; int count = 0; while(p!=NULL&&count<i-1) { p = p->next; count++; } // 因为我们上面查找的是i - 1这个位置,删除的却是 i ,所以p-> next 也不能为空 if(p == NULL&&p->next ==NULL) // 这里很重要!!结点p 或 p的后继结点不存在 throw"位置"; else{ q = p->next;x = q->data; // 暂存被删结点 p->next = q->next; // 摘链 delete q; return x; } } int linklist::locate(int x) { Node *p = first -> next; //工作指针p初始化 int count = 1; while(p != NULL) { if(p -> data == x) return count; p = p -> next; count++; } return 0; } void linklist::printlist() { Node *p = first->next; while(p!=NULL) { cout<<p->data<<" "; p=p->next; } cout<<endl; } int main() { int r[5]={1,2,3,4,5}; linklist L(r,5); // 建立单链表! cout<<"执行操作前数据为:"<<endl; L.printlist(); try { L.insert(2,3); // 在第二个位置插入3. } catch(char *s) { cout<<s<<endl; } cout<<"执行插入操作后的数据"<<endl; L.printlist(); cout<<"值为5的元素 位置 为:"; cout<<L.locate(5)<<endl; cout<<"执行删除操作前的数据为"<<endl; L.printlist(); try { L.Delete(1); // 删除第一个位置的元素; } catch(char *s) { cout<<s<<endl; } cout<<"执行删除操作后的数据为:"<<endl; L.printlist(); return 0; }
4、循环链表:在单链表中,如果将终端结点的指针域由空指针改为指向头结点,就使整个单链表形成一个环,这种头尾相接的单链表称为循环单链表,简称循环链表。
5、双链表: 在循环链表中,虽然从任一结点出发可以扫描到其他结点,但要找到其他前驱结点,则需要遍历整个循环链表。如果希望快速确定表中任一结点的前驱结点,可以在单链表的每个结点中再设置一个指向其前驱结点的指针域,这样就形成了双链表。
6、静态链表:静态链表是用数组来表示单链表,用数组元素的下标来模拟单链表的指针。
7、间接寻址:是将数组和指针结合起来的一种方法,它将数组中存储数据元素的单元改为存储指向该元素的指针。
数据结构——线性表(第二章)
时间: 2024-10-20 19:09:17