结构体 转string_从零开始学习数据结构>矩阵+串

数组 + 矩阵 + 串是常见的数据结构,需要深入掌握与学习。 对于数组:根据指定下标定位相关元素的地址是最为关键的操作,玩数组就是玩下标。 矩阵:M * N 的二维数组,是逻辑线性结构。 稀疏矩阵

1、基础概念

模型: 7409004d860922a2a1ab4a65a49b32b9.png 稀疏矩阵:矩阵中绝大多数元素为零,只有少量非零元素;稀疏因子 = 非零元素数量/矩阵总元素数量。 存储空间利用率:有效元素所申请空间/该矩阵所申请的空间。 定位:当给出下标i、j,且i、j在有效下标取值范围内,需要定位其所对应的元素在压缩存储方式中的位置。 2、代码实现 为提升空间利用率(只存储有效元素,避免空间过度浪费),矩阵的存储一般采用三元组法/十字交叉链。 三元组实现: 结构体
 1typedef struct TRIAD{
2    int value;
3    int row;
4    int col;
5}TRIAD;
6
7typedef struct TRIPLE{
8    TRIAD *element;
9    int rowCount;
10    int colCount;
11    int elementCount;
12}TRIPLE;
具体代码
  1#include 
2#include 
3
4typedef struct TRIAD{
5    int value;
6    int row;
7    int col;
8}TRIAD;
9
10typedef struct TRIPLE{
11    TRIAD *element;
12    int rowCount;
13    int colCount;
14    int elementCount;
15}TRIPLE;
16
17TRIPLE *inputTriple(void);
18void destoryTriple(TRIPLE *);
19void showMatrix(TRIPLE triple);
20TRIPLE *revangeMatrix(TRIPLE triple);
21TRIPLE *initTriple(int rowCount, int colCount, int elementCount);
22
23TRIPLE *initTriple(int rowCount, int colCount, int elementCount){
24    TRIPLE *triple;
25
26    triple = (TRIPLE *)malloc(sizeof(TRIPLE));
27    triple->rowCount = rowCount;
28    triple->colCount = colCount;
29    triple->elementCount = elementCount;
30
31    triple->element = (TRIAD *)malloc(sizeof(TRIAD) * elementCount);
32
33    return triple;
34}
35
36TRIPLE *revangeMatrix(TRIPLE triple){
37    TRIPLE *revTriple;
38    int *ec;
39    int i;
40    int index;
41
42    revTriple = initTriple(triple.rowCount, triple.colCount, triple.elementCount);
43    revTriple->rowCount = triple.colCount;
44    revTriple->colCount = triple.rowCount;
45    revTriple->elementCount = triple.elementCount;
46
47    ec = (int *)calloc(triple.colCount+1, sizeof(int));
48    for(i = 0; i  49        ec[triple.element[i].col + 1]++;    
50    }
51    for(i = 1; i 1; i++){
52        ec[i] += ec[i-1];
53    }
54    for(i = 0; i  55        index = ec[triple.element[i].col];
56        revTriple->element[index].col = triple.element[i].row; 
57        revTriple->element[index].row = triple.element[i].col;
58        revTriple->element[index].value = triple.element[i].value;
59        ec[index+1]++;
60    }
61
62    free(ec);
63
64    return revTriple;
65}
66
67void showMatrix(TRIPLE triple){
68    int i;
69    int j;
70    int t = 0;
71
72    for(i = 0; i  73        for(j = 0; j  74            if(i == triple.element[t].row && j == triple.element[t].col)
75                printf("%d\t", triple.element[t++].value);
76            else 
77                printf("0\t");
78        }
79        printf("\n");
80    }
81
82}
83
84void destoryTriple(TRIPLE *triple){
85    free(triple->element);
86    free(triple);
87}
88
89TRIPLE *inputTriple(void){
90    TRIPLE *triple;
91    int rowCount;
92    int colCount;
93    int elementCount;
94    int i;
95
96    scanf("%d%d%d", &rowCount, &colCount, &elementCount);   
97
98    triple = initTriple(rowCount, colCount, elementCount);
99
100    for(i = 0; i 101        int value;
102        int row;
103        int col;
104
105        scanf("%d%d%d", &row, &col, &value);
106        triple->element[i].row = row;
107        triple->element[i].col = col;
108        triple->element[i].value = value;
109    }
110
111    return triple;
112}
113
114void main(void){
115    TRIPLE *tr;
116    TRIPLE *revTr;
117
118    tr = inputTriple();
119
120    revTr = revangeMatrix(*tr);
121
122    showMatrix(*tr);
123    showMatrix(*revTr);
124
125    destoryTriple(tr);
126    destoryTriple(revTr);
127}
十字交叉链: 模型 67a2faf43e321179446cf9a5a78fa788.png 结构体
 1// 1、稀疏矩阵中的每一个元素的数据类型是 USER_TYPE,用户自定义数据类型
2typedef int USER_TYPE;
3
4// 2、十字交叉链中每一个节点的数据类型
5typedef struct NODE{
6    USER_TYPE data;
7    struct NODE *nextCol;
8    struct NODE *nextRow;
9}NODE;
10
11// 3、无论是行链表、列链表,都应该是多个链表,且用头指针作为起点
12typedef struct CROSS_LINK{
13    int rowCount;
14    int colCount;
15    NODE **rowHead;
16    NODE **colHead;
17}CROSS_LINK;
18
19CROSS_LINK *crossHead =    NULL; //通过头结点指针实现逻辑
具体代码实现较为复杂,暂时还没时间去实现这块具体的逻辑,有兴趣的读者,可以自行实现代码细节。 串 1、基础概念 串:数组 + 链表的结合是其基本组成结构。 涉及到经典算法:串匹配基础算法 --> KMP 串匹配算法(后续会写这个算法) 使用数组表达串的缺陷: (1)、长度不能够灵活变化; (2)、对于串中字符的插入、删除操作存在着大量的移动操作。 随机访问与顺序访问: (1)、随机访问是无需遍历直接定位的访问方式,通常指下标访问; (2)、顺序访问是必须重头开始逐一遍历的访问方式,通常指链表节点访问。 串的常见操作有:初始化串、销毁串、指定下标插入、删除、查找、替换、复制、连接、分割等等操作。 2、代码实现 模型 ebab378e00f8a65b4fb5ad03e8d28362.png 结构体
 1#define UNIT_LEN    16
2
3// 1、每一个节点的数据类型
4typedef struct STRING_UNIT{
5    char string[UNIT_LEN];
6    struct STRING_UNIT *next;
7    char len;
8}STRING_UNIT;
9
10// 2、头指针进行控制
11typedef struct STRING{
12    STRING_UNIT *stringHead;
13    int length;
14}STRING;
具体代码(实现 .h 文件)
  1#ifndef _MEC_STRING_H_
2#define _MEC_STRING_H_
3
4#include
5#include
6#include
7
8#define UNIT_LEN    16
9
10typedef struct STRING_UNIT{
11    char string[UNIT_LEN];
12    struct STRING_UNIT *next;
13    char len;
14}STRING_UNIT;
15
16typedef struct STRING{
17    STRING_UNIT *stringHead;
18    int length;
19}STRING;
20
21boolean initString(STRING **string);
22STRING_UNIT *creatStringUnit();
23void destoryString(STRING **string);
24void removeStringUintAt(STRING_UNIT *curUnit);
25void setStringUnitContent(STRING_UNIT *target, const char *source, int len);
26void stringCopy(STRING *string, const char *source);
27void showString(STRING string);
28
29void showString(STRING string){
30    int count = 0;
31    int index = 0;
32    STRING_UNIT *cur;
33    register char ch;
34
35    cur = string.stringHead;
36    while(cur && count string.length){
37        ch = cur->string[index];
38        if(ch){
39            putchar(ch);
40            count++;
41            if(++index >= UNIT_LEN){
42                index = 0;
43                cur = cur->next;
44            }
45        }
46    }
47}
48
49void stringCopy(STRING *string, const char *source){
50    STRING_UNIT *cur;
51    int sourceLen;
52    int dealedCount = 0;
53
54    sourceLen = strlen(source);
55    string->length = sourceLen;
56    cur = string->stringHead;
57
58    while(sourceLen > 0){       
59        setStringUnitContent(cur, source + dealedCount++ * UNIT_LEN,
60            sourceLen > UNIT_LEN ? UNIT_LEN : sourceLen);
61        sourceLen -= UNIT_LEN;
62
63        if(sourceLen > 0){
64            if(cur->next == NULL){
65                cur->next = creatStringUnit();
66            }
67            cur = cur->next;
68        }
69    }
70
71    while(cur->next){
72        removeStringUintAt(cur);
73    }
74
75}
76
77void setStringUnitContent(STRING_UNIT *target, const char *source, int len){
78    int index;
79
80    for(index = 0; index  81        target->string[index] = source[index];
82    }
83
84    while(index  85        target->string[index++] = 0;
86    }
87
88    target->len = len;
89}
90
91void removeStringUintAt(STRING_UNIT *curUnit){
92    STRING_UNIT *p;
93
94    if(curUnit->next){
95        p = curUnit->next;
96        curUnit->next = p->next;
97        free(p);
98    }
99}
100
101void destoryString(STRING **string){
102    STRING_UNIT *head;
103
104    if(!*string){
105        return; 
106    }
107
108    head = (*string)->stringHead;
109    while(head){
110        STRING_UNIT *p;
111
112        p = head;
113        head = head->next;
114        free(p);
115    }
116
117    free(*string);
118    *string = NULL;
119}
120
121STRING_UNIT *creatStringUnit(){
122    STRING_UNIT *head;
123
124    head = (STRING_UNIT *)calloc(sizeof(STRING_UNIT), 1);
125
126    head->len = 0;
127    head->next = NULL;
128
129    return head;
130}
131
132boolean initString(STRING **string){
133    if(*string){
134        return FALSE;
135    }
136
137    *string = (STRING *)malloc(sizeof(STRING));
138
139    (*string)->stringHead = creatStringUnit();
140    (*string)->length = 0;
141
142    return TRUE;
143}
144
145#endif
三元组、十字交叉链、KMP 算法、串(数组+链表)实现方式是数据结构中最基础部分,这部分需要消化吃透。 推荐阅读: 从零开始学习数据结构-->入门篇 从零开始学习数据结构-->链表 从零开始学习数据结构-->线性表 从零开始学习数据结构-->栈 从零开始学习数据结构-->队列 认真的人 自带光芒

0c0d77332cbaa846b2b3d13060874fc7.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值