当前位置:   article > 正文

数据结构① 线性表_数据结构adt例子

数据结构adt例子

目录

基本概念和术语

ADT定义

引用类型

线性表 

线性表的顺序表示 

顺序表的链式表示 

单链表

循环链表

双向链表

线性表应用

线性表合并

有序表合并

多项式相加

顺序表示

 链式表示

队列

循序表示

链式表示

数组

特殊矩阵的压缩存储


基本概念和术语

ADT定义

模板:

        ADT 抽象数据类型名{
            数据对象定义
            数据元素之间逻辑关系定义
            操作
                初始条件
                操作结果
        }ADT 抽象数据类型名

举例(圆)

  1. ADT Circle{
  2. D = {r , x , y | r , x , y 均为实数} //数据对象
  3. R = {< r , x , y > | r 是半径 , < x , y >是圆心坐标} //数据关系
  4. /*基本操作 ↓*/
  5. Circle(&C , r , x , y) //操作结果:构造一个圆
  6. double Area(C) //初始条件:圆已存在
  7. //操作结果:计算面积
  8. double Circumference(C) //初始条件:圆已存在
  9. //操作结果:计算周长
  10. ……
  11. }ADT Circle

引用类型

  1. #include<stdio.h>
  2. int main(){
  3. int i = 5;
  4. /*引用*/
  5. int &j = i; //引用类型
  6. i--;
  7. printf("%d %d\n",i,j); //4 4
  8. return 0;
  9. }
  1. #include<stdio.h>
  2. void swap(int& m , int& n);
  3. int main(){
  4. int a = 5 , b = 6;
  5. swap(a , b);
  6. printf("%d %d\n",a,b); //6 5
  7. return 0;
  8. }
  9. void swap(int& m , int& n){
  10. int mid;
  11. mid = m;
  12. m = n;
  13. n = mid;
  14. }

线性表 

线性表的顺序表示 

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #define MAXSIZE 100
  4. typedef struct{
  5. float p;
  6. int e;
  7. }Polynomial;
  8. /*数组动态分布*/
  9. typedef struct{
  10. Polynomial *elem;
  11. int lenth;
  12. }SqList;
  13. /*数组静态分布*/
  14. //typedef struct{
  15. // Polynomial data[MAXSIZE];
  16. // int lenth;
  17. //}SqList;
  18. void DestroyList(SqList &L);
  19. void ClearList(SqList &L);
  20. int GetLenth(SqList L);
  21. int IsEmpty(SqList L);
  22. int GetElem(SqList L , int i , Polynomial &e);
  23. int ListInsert(SqList &L , int i , Polynomial e);
  24. int ListDelet(SqList &L , int i , Polynomial );
  25. int main(){
  26. SqList L;
  27. L.elem = (Polynomial*)calloc(MAXSIZE , sizeof(Polynomial));
  28. return 0;
  29. }
  30. void DestroyList(SqList &L){
  31. if(L.elem) free(L.elem);
  32. }
  33. void ClearList(SqList &L){
  34. L.lenth = 0;
  35. }
  36. int GetLenth(SqList L){
  37. return L.lenth;
  38. }
  39. int IsEmpty(SqList L){
  40. if(L.lenth == 0){
  41. return 1;
  42. }
  43. return 0;
  44. }
  45. int GetElem(SqList L , int i , Polynomial &e){
  46. if(i < 1 || i > L.lenth) return 0; //故障
  47. //(我不理解为什么是 <1 而不是 <0)
  48. e = L.elem[i - 1];
  49. return 1;
  50. }
  51. int ListInsert(SqList &L , int i , Polynomial e){
  52. if(i < 1 || i > L.lenth + 1) return 0; //(我不理解为什么是 <1 而不是 <0)
  53. if(L.lenth == MAXSIZE) return 0;
  54. for(int j = L.lenth - 1 ; j >= i - 1 ; j--){
  55. L.elem[j + 1] = L.elem[j];
  56. }
  57. L.elem[i - 1] = e;
  58. L.lenth++;
  59. return 1;
  60. }
  61. int ListDelete(SqList &L , int i){
  62. if(i < 1 || i > L.lenth) return 0; //(我不理解为什么是 <1 而不是 <0)
  63. for(int j = i ; j <= L.lenth - 1 ; j++){
  64. L.elem[j - 1] = L.elem[j];
  65. }
  66. L.lenth--;
  67. return 1;
  68. }

线性表

顺序表:随机存取(数组)

链表:顺序存储

  1. /*Way One*/
  2. typedef struct Student{
  3. char num[10]; //数据域
  4. char name[10]; //数据域
  5. int score; //数据域
  6. Student* next; //指针域
  7. }Student;
  8. /*Way Two*/
  9. typedef struct ElemType{
  10. char num[10]; //数据域
  11. char name[10]; //数据域
  12. int score; //数据域
  13. }ElemType;
  14. typedef struct Student{
  15. ElemType data; //数据域
  16. Student* next; //指针域
  17. }Student;
  18. //Way Two 更受欢迎

顺序表的链式表示 

单链表

  1. #include<stdio.h>
  2. typedef struct LNode{
  3. int data;
  4. struct LNode* next;
  5. }Lnode , *LinkList;
  6. //LinkList 为指向结构体Lnode的指针
  7. //LinkList p 和 Lnode *p , 两个p等价,都存放地址
  8. int main(){
  9. /*定义链表L常用*/
  10. LinkList L;
  11. /*而非 Lnode* L 尽管两者等价*/
  12. /*定义结点指针p常用*/
  13. Lnode *p;
  14. /*而非LinkList p 尽管两者等价*/
  15. return 0;
  16. }

  1. #include<stdio.h>
  2. typedef struct LNode{
  3. int data;
  4. struct LNode* next;
  5. }LNode , *LinkList;
  6. //LinkList 为指向结构体Lnode的指针
  7. //LinkList p 和 Lnode *p , 两个p等价,都存放地址
  8. void InitList_L(LinkList &L);
  9. int ListEmpty(LinkList L);
  10. void DestroyList(LinkList &L);
  11. void ClearList(LinkList &L);
  12. int ListLength(LinkList L);
  13. void GetElem(LinkList L , int i , int &e); //把第i个放在e里传回来
  14. LNode* LocateElem1(LinkList L , int e);//康康e是不是在单链表里,return 位置哦
  15. int LocateElem2(LinkList L , int e);//与上一个不同,return位置序号
  16. int main(){
  17. /*定义链表L常用*/
  18. LinkList L;
  19. /*而非 Lnode* L 尽管两者等价*/
  20. /*定义结点指针p常用*/
  21. LNode *p;
  22. /*而非LinkList p 尽管两者等价*/
  23. return 0;
  24. }
  25. void InitList_L(LinkList &L){
  26. L = new LNode;
  27. L->next = NULL;
  28. }
  29. //判断链表是否为空,只要判断第一个的指针域是不是NULL(0)
  30. int ListEmpty(LinkList L){
  31. if(L->next) return 0;
  32. return 1;
  33. }
  34. void DestroyList(LinkList &L){
  35. LNode* p;
  36. while(L){
  37. p = L;
  38. L = L->next;
  39. delete p;
  40. }
  41. }
  42. void ClearList(LinkList &L){
  43. LNode* p1 = L->next;
  44. while(p1){
  45. LNode* p2 = p1->next;
  46. delete p1;
  47. p1 = p2;
  48. }
  49. L->next = NULL;
  50. }
  51. int ListLength(LinkList L){
  52. LNode* p = L;
  53. int length = 0;
  54. while(p){
  55. p = p->next;
  56. length++;
  57. }
  58. length--; //头结点记得减掉
  59. return length;
  60. }
  61. void GetElem(LinkList L , int i , int &e){
  62. LNode* p = L->next ;
  63. while(p && i--){
  64. p = p->next;
  65. }
  66. if(i != 0 && p==0) e = 0; //那个元素不存在
  67. e = p->data;
  68. }
  69. LNode* LocateElem1(LinkList L , int e){
  70. LNode* p = L->next;
  71. while(p && p->data != e){
  72. p = p -> next;
  73. }
  74. return p;
  75. }
  76. int LocateElem(LinkList L , int e){
  77. LNode* p = L->next;
  78. int cnt = 0;
  79. while(p && e != p->data){
  80. p = p->next;
  81. cnt++;
  82. }
  83. return cnt;
  84. }

(插入删除头插尾插和链表那个博客重了,其实都重了,嘿嘿嘿,只是这个喜欢多个头结点)

 

 

 

  1. #include<stdio.h>
  2. typedef struct ElemType {
  3. int data1;
  4. float data2;
  5. char data3[10];
  6. } ElemType;
  7. typedef struct LNode {
  8. ElemType data;
  9. struct LNode* next;
  10. } LNode, *LinkList;
  11. void CreatList_H(LinkList &L , int n) {
  12. L = new LNode;
  13. L -> next = NULL;
  14. while(n--){
  15. LNode* p = new LNode;
  16. scanf("%d %lf %s",p -> data.data1 , p -> data.data2 , p -> data.data3);
  17. p ->next = L -> next;
  18. L -> next = p;
  19. }
  20. }

 

 

  1. #include<stdio.h>
  2. typedef struct ElemType {
  3. int data1;
  4. float data2;
  5. char data3[10];
  6. } ElemType;
  7. typedef struct LNode {
  8. ElemType data;
  9. struct LNode* next;
  10. } LNode, *LinkList;
  11. void CreatList_T(LinkList &L , int n) {
  12. L = new LNode;
  13. L -> next = NULL;
  14. LNode *t = new LNode;
  15. while(n--){
  16. LNode *p = new LNode;
  17. scanf("%d %lf %s",p -> data.data1 , p -> data.data2 , p -> data.data3);
  18. p -> next = NULL;
  19. t -> next = p;
  20. t = p;
  21. }
  22. }

循环链表

  1. #include<stdio.h>
  2. typedef struct LNode{
  3. int data;
  4. struct LNode* next;
  5. }LNode , *LinkList;
  6. void LinkList_Connect(LinkList &Ta , LinkList Tb);
  7. /*Attention T 指的是尾指针*/
  8. int main(){
  9. return 0;
  10. }
  11. void LinkList_Connect(LinkList &Ta , LinkList Tb){
  12. LNode* p = Ta->next; //p指向a的头指针
  13. Ta->next = Tb->next->next; //(1)
  14. delete Tb->next; //b的头指针delete
  15. Tb->next = p; //(2)
  16. }

 

双向链表

  1. #include<stdio.h>
  2. typedef struct DuLNode{
  3. int data;
  4. struct DuLNode *prior , *next;
  5. }DuLNode , *DuLinkList;
  6. DuLNode* GetElem_DuL(DuLinkList L , int i);
  7. //得到双向链表L的第i个位置的地址
  8. void ListInsert_Dul(DuLinkList &L , int i , int e);
  9. //在双向链表L的第i个位置之前插入元素e
  10. int main(){
  11. return 0;
  12. }
  13. DuLNode* GetElem_DuL(DuLinkList L , int i){
  14. DuLNode* p = L->next;
  15. while(i--) p = p->next;
  16. return p;
  17. }
  18. void ListInsert_Dul(DuLinkList &L , int i , int e){
  19. DuLNode* p = GetElem_DuL(L , i);
  20. DuLNode* q = new DuLNode;
  21. q->data = e;
  22. q->prior = p->prior;
  23. p->prior->next = q;
  24. p->prior = q;
  25. q->next = p;
  26. }

 

  1. #include<stdio.h>
  2. typedef struct DuLNode{
  3. int data;
  4. struct DuLNode *prior , *next;
  5. }DuLNode , *DuLinkList;
  6. DuLNode* GetElem_DuL(DuLinkList L , int i);
  7. //得到双向链表L的第i个位置的地址
  8. void ListDelete_DuL(DuLinkList &L , int i);
  9. //删除双向链表L的第i个元素
  10. int main(){
  11. return 0;
  12. }
  13. DuLNode* GetElem_DuL(DuLinkList L , int i){
  14. DuLNode* p = L->next;
  15. while(i--) p = p->next;
  16. return p;
  17. }
  18. void ListDelete_DuL(DuLinkList &L , int i){
  19. DuLNode* p = GetElem_DuL(L , i);
  20. p->prior->next = p->next;
  21. p->next->prior = p->prior;
  22. delete(p);
  23. }

 

线性表应用

线性表合并

 

有序表合并

 

顺序表实现

 代码实现:

  1. #include<stdio.h>
  2. typedef struct SqList{
  3. int* elem;
  4. int length;
  5. }SqList;
  6. int main(){
  7. return 0;
  8. }
  9. void MergeList_Sq(SqList LA , SqList LB , SqList &LC){
  10. int* pa = LA.elem;
  11. int* pb = LB.elem;
  12. LC.length = LA.length + LB.length;
  13. LC.elem = new int[LC.length];
  14. int* pc = LC.elem;
  15. int* pa_last = LA.elem + LA.length - 1;
  16. int* pb_last = LB.elem + LB.length - 1;
  17. while(pa != pa_last && pb != pb_last){
  18. if(*pa <= *pb) *pc++ = *pa++;
  19. else *pc++ = *pb++;
  20. }
  21. while(pa <= pa_last) *pc++ = *pa++;
  22. while(pb <= pb_last) *pc++ = *pb++;
  23. }

链表实现

代码实现 :

  1. #include<stdio.h>
  2. typedef struct LNode{
  3. int data;
  4. struct LNode* next;
  5. }LNode , *LinkList;
  6. int main(){
  7. return 0;
  8. }
  9. void MergeList_L(LinkList &La , LinkList &Lb , LinkList &Lc){
  10. LNode* pa = La->next;
  11. LNode* pb = Lb->next;
  12. Lc = La;
  13. LNode* pc = Lc;
  14. while(pa && pb){
  15. if(pa->data <= pb->data){
  16. pc->next = pa;
  17. pc = pa;
  18. pa = pa->next;
  19. }else{
  20. pc->next = pb;
  21. pc = pb;
  22. pb = pb->next;
  23. }
  24. }
  25. pc->next = pa?pa:pb;
  26. delete Lb;
  27. }

多项式相加

  1. #include<stdio.h>
  2. typedef struct PNode{
  3. float x;//系数
  4. int z; //指数
  5. struct PNode *next;
  6. }PNode , *Polynomial;
  7. int main(){
  8. return 0;
  9. }
  10. void Add_Polynomial(Polynomial P , Polynomial Q , Polynomial &R){
  11. PNode* p = P->next;
  12. PNode* q = Q->next;
  13. R = P;
  14. PNode* t = R;
  15. while(q && p){
  16. if(p->z == q->z && (p->x + q->x) != 0){
  17. t->next = p;
  18. p->x += q->x;
  19. t = p;
  20. p = p->next;
  21. q = q->next;
  22. }else if(p->z < q->z){//p小
  23. t->next = p;
  24. t = p;
  25. p = p->next;
  26. }else{//q小
  27. t->next = q;
  28. t = q;
  29. q = q->next;
  30. }
  31. }
  32. if(q) t->next = q;
  33. if(p) t->next = p;
  34. delete(Q);
  35. }

后进先出(一口封闭)

top = base 是空栈标志

top - base = stacksize 是栈满的标志

顺序表示

InitStack:

 

 

 代码实现:

  1. #include<stdio.h>
  2. #define MAXSIZE 100
  3. typedef struct SqStack{
  4. int* base;
  5. int* top;
  6. int stacksize;
  7. }SqStack;
  8. void InitStack(SqStack &S);
  9. int main(){
  10. return 0;
  11. }
  12. void InitStack(SqStack &S){
  13. S.base = new int[MAXSIZE];
  14. // if(!S.base) 存储分配失败,可以报警
  15. S.top = S.base;
  16. S.stacksize = MAXSIZE;
  17. }

StackEmpty:

  1. int StackEmpty(SqStack S){
  2. if(S.top == S.base) return 1; //true
  3. return 0;
  4. }

StackLength:

  1. int StackLenfth(SqStack S){
  2. return (S.top - S.base) ;
  3. }

ClearStack:

  1. void ClearStack(SqStack &S){
  2. S.top = S.base;
  3. }

 DeleteStack:

  1. void DeleteStack(SqStack &S){
  2. delete S.base;
  3. S.stacksize = 0;
  4. S.base = S.top = NULL;
  5. }

 Push:

  1. int Push(SqStack &S , int e){
  2. if(S.top - S.base == S.stacksize)
  3. return 0;
  4. *S.top++ = e;
  5. return 1;
  6. }

  1. int Pop(SqStack &S , int &e){
  2. if(S.top == S.base)
  3. return 0;
  4. e = *--S.top;
  5. return 1;
  6. }

 链式表示

InitStack:

  1. #include<stdio.h>
  2. typedef struct StackNode{
  3. int data;
  4. struct StackNode* next;
  5. }StackNode , *LinkStack;
  6. void InitStack(LinkStack &S);
  7. int main(){
  8. LinkStack S;
  9. return 0;
  10. }
  11. void InitStack(LinkStack &S){
  12. S = NULL;
  13. }

 StackEmpty:

  1. int StackEmpty(LinkStack S){
  2. if(S == NULL)
  3. return 1;//true
  4. return 0; //false
  5. }

Push: 

  1. void Push(LinkStack &S , int e){
  2. StackNode* p = new StackNode;
  3. p->data = e;
  4. p->next = S;
  5. S = p;
  6. }

 Pop:

  1. void Pop(LinkStack &S , int e){
  2. //if(S == NULL) 空溢
  3. e = S->data;
  4. StackNode* p = S;
  5. S = S->next;
  6. delete p;
  7. }

 GetTop:

递归与栈

队列

 

先进先出(类似排队)

循序表示

Init: 

  1. #include<stdio.h>
  2. #define MAXSIZE 100
  3. typedef struct{
  4. int *base;
  5. int front;
  6. int rear;
  7. }SqQueue;
  8. void InitQueue(SqQueue &Q){
  9. Q.base = new int[MAXSIZE];
  10. //if(!Q.base) 溢出
  11. Q.front = Q.rear = 0;
  12. }
  13. int main(){
  14. return 0;
  15. }

Length: 

  1. int QueueLength(SqQueue Q){
  2. return (Q.rear - Q.front + MAXSIZE) % MAXSIZE ;
  3. }

In: 

  1. void EnQueue(SqQueue &Q , int e){
  2. //if((Q.rear + 1) % MAXSIZE == Q.front) 溢出
  3. Q.base[Q.rear] = e;
  4. Q.rear = (Q.rear + 1) % MAXSIZE;
  5. }

Out: 

  1. void DeQueue(SqQueue &Q , int e){
  2. //if(Q.rear == Q.front) 队空
  3. e = Q.base[Q.front];
  4. Q.front = (Q.front + 1) % MAXSIZE;
  5. }

GetHead: 

  1. int GetHeadQueue(SqQueue Q){
  2. //if(Q.rear == Q.front) 队空
  3. return Q.base[Q.front];
  4. }

链式表示

Init:

  1. #include<stdio.h>
  2. #define MAXSIZE 100
  3. typedef struct Qnode{
  4. int data;
  5. struct Qnode* next;
  6. }QNode , *QueuePtr;
  7. typedef struct{
  8. QueuePtr front;
  9. QueuePtr rear;
  10. }LinkQueue;
  11. void InitQueue(LinkQueue &Q){
  12. Q.front = Q.rear = new QNode;
  13. Q.front -> next = NULL;
  14. }
  15. int main(){
  16. return 0;
  17. }

Destroy: 

  1. void DestroyQueue(LinkQueue &Q){
  2. while(Q.front){
  3. QNode* p = Q.front->next;
  4. delete Q.front;
  5. Q.front = p;
  6. }
  7. }

In: 

  1. void EnQueue(LinkQueue &Q , int e){
  2. QNode* p = new(QNode);
  3. p->data = e;
  4. p->next =NULL;
  5. Q.rear->next = p;
  6. Q.rear = p;
  7. }

Out: 

  1. void DeQueue(LinkQueue &Q , int &e){
  2. //if(Q.front == Q.rear) 队空
  3. QNode* p = Q.front->next;
  4. e = p.data;
  5. Q.front = p->next;
  6. if(Q.rear == p) //删的恰好是尾结点
  7. Q.rear = Q.front;
  8. delete p;
  9. }

GetHead: 

  1. void GetHeadQueue(LinkQueue Q , int &e){
  2. //if(Q.front == Q.rear) 队空
  3. e = Q.front->next->data;
  4. }

特殊的线性表(只存char)

顺序表示:

  1. #include<stdio.h>
  2. #define MAXLEN 255
  3. typedef struct {
  4. char ch[MAXLEN + 1];
  5. int length;
  6. }SString;
  7. int main(){
  8. return 0;
  9. }

*顺序表示更常见! 

链式表示: 

  1. #include<stdio.h>
  2. #define CHUNKSIZE 80
  3. typedef struct Chunk{
  4. char ch[CHUNKSIZE];
  5. struct Chunk* next;
  6. }Chunk;
  7. typedef struct{
  8. Chunk *head , *tail;
  9. int curlen;
  10. }LString;
  11. int main(){
  12. return 0;
  13. }

字符串匹配度算法: 

普通:

  1. //从pos位置开始找与子串T符合的
  2. int Index_BF(SString S , SString T , int pos){
  3. int i = pos , j = 1;
  4. while(i <= S.length && j <= T.length){
  5. if(S.ch[i] == T.ch[j]){
  6. i++,j++;
  7. }else{
  8. i = i + j + 2;
  9. j = 1;
  10. }
  11. }
  12. if(i > S.length) return 0;
  13. return i - T.length;
  14. }

算法复杂度:O(m*n) 

KMP:

算法复杂度:O(m+n)

实例:

  1. #include<stdio.h>
  2. #define MAXLEN 255
  3. typedef struct {
  4. char ch[MAXLEN + 1];
  5. int length;
  6. }SString;
  7. void get_next(SString T , int (&next)[]){ //没有()会报错!
  8. int i = 1 , j = 0;
  9. next[1] = 0;
  10. while(i <= T.length){
  11. if(j==0 || T.ch[i] ==T.ch[j]){
  12. next[++i] = ++j;
  13. }else{
  14. j = next[j];
  15. }
  16. }
  17. }
  18. int Index_BF(SString S , SString T , int pos){
  19. int i = pos , j = 1;
  20. while(i <= S.length && j <= T.length){
  21. if(S.ch[i] == T.ch[j]){
  22. i++,j++;
  23. }else{
  24. j = next[j];
  25. //i不变
  26. }
  27. }
  28. if(i > S.length) return 0;
  29. return i - T.length;
  30. }
  31. int main(){
  32. return 0;
  33. }

next函数难理解,忘了回看 ↓ 

 (bilibili)凡三岁爱学习(KMP算法之求next数组代码讲解

数组

线性表结构是数组结构的特例,数组结构是线性结构的拓展

特殊矩阵的压缩存储

对称矩阵

 

 

(第一次画图上传QwQ)

三角矩阵 

上三角推导: 

 对角矩阵(带状矩阵)

稀疏矩阵

顺序存储:

链式存储: 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/空白诗007/article/detail/801658
推荐阅读
相关标签
  

闽ICP备14008679号