数据结构十字链表有向图(总)代码
数据结构经典题目及c语言代码
数据结构经典题目及c语言代码一、线性表1. 顺序表顺序表是一种利用连续存储空间存储元素的线性表。
以下是一个顺序表的经典题目及C语言代码实现:```c#define MaxSize 50typedef struct {int data[MaxSize]; // 存储元素的数组int length; // 顺序表的当前长度} SeqList;// 初始化顺序表void initList(SeqList *L) {L->length = 0;}// 插入元素到指定位置void insert(SeqList *L, int pos, int elem) {if (pos < 1 || pos > L->length + 1) {printf("插入位置无效\n");return;}if (L->length == MaxSize) {printf("顺序表已满,无法插入\n"); return;}for (int i = L->length; i >= pos; i--) { L->data[i] = L->data[i - 1];}L->data[pos - 1] = elem;L->length++;}// 删除指定位置的元素void delete(SeqList *L, int pos) {if (pos < 1 || pos > L->length) {printf("删除位置无效\n");return;}for (int i = pos - 1; i < L->length - 1; i++) {L->data[i] = L->data[i + 1];}L->length--;}// 获取指定位置的元素值int getElement(SeqList *L, int pos) {if (pos < 1 || pos > L->length) {printf("位置无效\n");return -1;}return L->data[pos - 1];}```2. 链表链表是一种利用非连续存储空间存储元素的线性表。
《大话数据结构》勘误(第一二三次印刷,按页码顺序整理)
《大话数据结构》简体中文版勘误(第一二三次印刷)尽管已经很仔细的检查和审核,但错误还是没有能避免。
以下的错误,有些是作者的笔误或者表述不清,有些是编辑审稿时不理解造成的错误,有些是美编改图时的错误,有些是印刷厂印刷时的错误。
虽然出错的原因很多,但总的来说都会给读者阅读时造成困扰,所以再次向读者说一声对不起!以便可以获得最新的勘误信息。
现勘误如下:注:★★★、★★和★为建议马上修改,它们之间程度不同,没有星为可改可不改,不影响阅读。
第一次印刷:1.1★★ P35,第一行,有一个“+”号应该是“=”,见下图1.2★ P38,倒数第二行,“速度其实只提高了10”,后面增加一个“倍”字。
1.3P111,第三段,第二行,“打算了Reset时”,多了一个“了”字。
目录P15,同样的问题。
1.4★★★ P268,P269,图7-7-14,图7-7-15,图7-7-16横竖条中都是有符号或数字的,目前因印刷问题没有显示。
1.5P377 “时间性能”这一段中 "事实上,移动可以通过改为记录的存储方式来予以避免" ,其中“改为”应该是“改变”第二次印刷:2.1P20,代码中“int i,sum =0, n = 100;”中的"i,"是多余的,可以删除,因为没有用到i变量。
(AGPSky提供)2.2P26,倒数第四行最后,“运算100次是运算10次的100”,应该是“运算10次的1000”。
(laciqs提供)2.3P43,图3-2-2,在天秤和射手之间,少了一个“天蝎座”。
( 小老K提供)2.4★★★ P46,union代码,有不少的问题,修正如下图。
union是C语言的关键字,因此函数名增加一个L。
具体实现代码,请参见源代码中的“01线性表顺序存储_List.c”文件(laciqs提供)2.5P52,代码中间部分,“for(k=L>length-1;k>=i-1;k--”后面少了一个“)”。
数据结构--图重点
DFSTree(G, w, q, visited);
生成森林:不完全图中的各个连通分量的生成树,构成图的生成森林
二、存储结构
顶点:可采用链表或数组存储顶点列表,一般采用链表存储
边:1.邻接矩阵(数组)
a.无向图:对称阵,可采用矩阵压缩存储方式。A[i][j] = 0表示 和 没有连接;A[i][j]= 1表示 和 有边连接;第i行的和表示顶点 的度
b.有向图:不对称阵。 表示顶点 到 的有向弧的权值; 表示表示顶点 到 没有弧连接或者i = j
enQueue(Q, w);
}
w = getNextNeighbor(G, v, w);
}
}
delete[] visited;
}
四、图的连通性问题(无向图)
1.深度优先生成树(深度优先搜索形成),广度优先生成树(广度优先搜索形成)
深度优先生成森林算法:
void DFSForest(Graph G, CSTree& T) {
CSTree q=null;
int n = G.vexnum;
bool* visited = new bool[n];
for(int i = 0; i < n; i++)visited[i] = false;
for (int v = 0; v < n; v++) {
if (!visited[v]) {
}
}
}
深度优先生成树算法:
void DFSTree(Graph G, int v, CSTree T, bool& visited[]){
visited[v] = true;
计算机专业基础综合数据结构(图)历年真题试卷汇编4
计算机专业基础综合数据结构(图)历年真题试卷汇编4(总分:58.00,做题时间:90分钟)一、综合题(总题数:7,分数:14.00)1.已知一图如下图所示:(1)写出全部拓扑排序;(2)以V1为源点,以V8为终点,给出所有事件允许发生的最早时间和最晚时间,并给出关键路径;(3)求V1结点到各点的最短距离。
【北京邮电大学2000五(15分)】__________________________________________________________________________________________正确答案:(正确答案:关键路径有3条,长17。
各事件允许发生的最早时间和最晚时间略。
V1→V2→V6→V8,V1→V3→V5→V7→V8,V1→V7→V8→V1→V4→V5→V8 (3)V1结点到其他各结点的最短距离为:2,3,6,12,10,15,16。
)2.(1)对于有向无环图,叙述求拓扑有序序列的步骤;(2)对于以下的图,写出它的四个不同的拓扑有序序列。
【南开大学1998二(12分)】__________________________________________________________________________________________ 正确答案:(正确答案:(1)对有向图,求拓扑序列步骤为: 1)在有向图中选一个没有前驱(即入度为零)的顶点并输出。
2)在图中删除该顶点及所有以它为尾的弧。
3)重复1)和2),直至全部顶点输出,这时拓扑排序完成;否则,图中存在环,拓扑排序失败。
(2)这里使用形式化描述方法,当有多个顶点可以输出时,将其按序从上往下排列,这样不会丢掉拓扑序列。
这里只画出从顶点1开始的所有可能的拓扑序列,从顶点3开始的拓扑序列可类似画出。
)3.有向图的拓扑排序能否用图的深度搜索模式来查找?若能,请简述方法;若不能,请简述原因。
【西北大学2000二、8(5分)】__________________________________________________________________________________________ 正确答案:(正确答案:图的深度优先遍历可用于拓扑排序。
数据结构中有向图和无向图的c语言实现
#include<iostream.h>
#include<malloc.h>
#define M 50
typedef char vextype;//顶点数据类型char
typedef struct node //定义表结点类型
{
int adjvex;//邻接点域
struct node *link;//指针域
}
cout<<"以(0,0)为输入结束符"<<endl;
cout<<"输入一条边依附的两个顶点序号:";
cin>>i>>j;
while((i>0)&&(j>0))//输入的(i,j)为(0,0)作为结束符号
{
p=(edgenode*)malloc(sizeof(edgenode));//生成邻接序号为j的表结点
break;
default:cout<<"输入错误,程序结束!"<<endl;
return;
}
cout<<endl;
cout<<"是否继续?(输入n结束,输入y有效!)"<<endl;
cin>>flag;
}
cout<<"程序结束,再见!"<<endl;
}
}edgenode,*Edgenode;
typedef struct headnode//定义表头结点类型
{
vextype vexdata;//顶点数据域
王道考研数据结构代码总结
王道考研数据结构代码总结⽬录⼀、线性表1.顺序表#include<stdlib.h>#include<stdio.h>#include<iostream>using namespace std;#define InitSize 10 //定义最⼤长度静态分配//typedef struct {// int data[InitList];// int length;//}SqlList;//动态分配typedef struct {int *data;int length; //当前长度int MaxSize;//最⼤长度}SqlList;//初始化顺序表void InitList(SqlList &L) {L.data = (int *)malloc(InitSize * sizeof(int));L.length = 0;L.MaxSize = InitSize;}//增加顺序表的长度void IncreaseSize(SqlList &L, int len) {int* p = L.data;L.data = (int*)malloc((L.MaxSize + len) * sizeof(int));for (int i = 0; i < L.length; i++) {L.data[i] = p[i];}L.MaxSize += len;free(p);}//插⼊元素,在位序i的位置插⼊元素ebool ListInsert(SqlList& L, int i, int e) {if (i<1 || i>L.length + 1) return false; //i的范围是否有效if (L.length >= L.MaxSize) return false; //当前存储空间已满,不能插⼊for (int j = L.length; j >= i; j--) {L.data[j] = L.data[j - 1];}L.data[i - 1] = e;L.length++;L.length++;return true;}//删除操作,删除位序i个位置上的元素,e是删除的元素bool ListDelete(SqlList& L, int i, int& e) {if (i<1 || i>L.length) return false;e = L.data[i - 1];for (int j = i; j < L.length; j++) {L.data[j-1] = L.data[j];}L.length--;return true;}//按位查找返回位序i的元素int GetElem(SqlList L, int i) {if (i<1 || i>L.length) return -1;return L.data[i - 1];}//查找第⼀个元素值等于e的元素,并返回其位序int LocateElem(SqlList L, int e) {for (int i = 0; i < L.length; i++) {if (L.data[i] == e) return i + 1;}return -1;}//删除值位于s和t之间的数bool Delete_s_t(SqlList& L, int s, int t) {if (L.length == 0 || s >= t) return false;int k = 0;for (int i = 0; i < L.length; i++) {if (L.data[i]<s || L.data[i]>t) {L.data[k++] = L.data[i];}}L.length = k;return true;}int main() {SqlList L;InitList(L);ListInsert(L, 1, 1);ListInsert(L, 2, 6);ListInsert(L, 3, 3);ListInsert(L, 4, 8);ListInsert(L, 5, 2);for (int i = 0; i < L.length; i++) {cout << L.data[i] << " ";}cout << endl;Delete_s_t(L, 2, 3);for (int i = 0; i < L.length; i++) {cout << L.data[i] << " ";}cout << endl;return 0;}2.单链表(不带头结点)#include<iostream>#include<algorithm>using namespace std;typedef struct LNode {int data;struct LNode* next;}LNode, * LinkList;//struct LNode* == LinkList//强调节点⽤LNode//强调链表⽤LinkList//初始化单链表bool InitList(LinkList& L) {L = NULL;return true;}//按位查找,返回第i个元素(不带带头节点)LNode* GetElem(LinkList L, int i) {if (i <= 0) return NULL;int j = 1;LNode* p = L;while (p && j < i) {p = p->next;j++;}return p;}//按值查找,找到数据域等于e的节点LNode* LocateElem(LinkList L, int e) {LNode* p = L;while (p && p->data != e) {p = p->next;}return p;}//统计单链表的长度int Length(LinkList L) {int len = 0;LNode* p = L;while (p) {len++;p = p->next;}return len;}//后插操作,在节点p之后插⼊元素ebool InsertNextNode(LNode* p, int e) {if (!p) return false;LNode* s = (LNode*)malloc(sizeof(LNode)); if (!s) return false;s->data = e;s->next = p->next;p->next = s;return true;}//不带头节点的插⼊操作,在第i个位置插⼊元素ebool ListInsert(LinkList& L, int i, int e) {if (i < 1) return false;if (i == 1) {LNode* s = (LNode*)malloc(sizeof(LNode));s->data = e;s->next = L;L = s;return true;}LNode* p;p = L;int j = 1; //当前p指向的是第⼏个节点,没有头节点,所以从1开始 while (p && j < i - 1) {p = p->next;j++;}if (!p) return false;return InsertNextNode(p, e);}//前插操作,在p节点前插⼊元素ebool InsertPriorNode(LNode* p, int e) {if (!p) return false;LNode* s = (LNode*)malloc(sizeof(LNode));if (!s) return false;s->next = p->next;p->next = s;s->data = p->data;p->data = e;return true;}//前插操作,在节点p之前插⼊节点sbool InsertPriorNode(LNode* p, LNode* s) {if (!p || !s) return false;s->next = p->next;p->next = s;swap(s->data, p->data);return true;}//删除位序i的节点,e是i节点的值bool ListDelete(LinkList& L, int i, int& e) {if (L == NULL) {e = -1;return false;}if (i < 1) return false;if (i > 1) {LNode* p = GetElem(L, i - 1);if (!p || !(p->next)) return false;LNode* q = p->next;e = q->data;p->next = q->next;free(q);}else {if (L->next == NULL) {e = L->data;L = NULL;}else {e = L->data;L = L->next;L = L->next;}}return true;}//删除指定节点Pbool DeleteNode(LNode* p) {if (p->next == NULL) return false;//下⾯这段代码有bug,不能删除最后⼀个节点,因此要是删除最后⼀个节点的话要重新进⾏操作 LNode* q = p->next;p->data = q->data;p->next = q->next;free(q);return true;}//尾插法,不带头结点LinkList List_TailInsert(LinkList& L) {InitList(L);LNode* s, * r = L ; //r表⽰表尾指针int x;bool is_head = true;while (cin >> x) {s = (LNode*)malloc(sizeof(LNode));if (is_head) {is_head = false;s->data = x;L = s;r = s;}s->data = x;r->next = s;r = s;}r->next = NULL;return L;}//头插法,不带头结点LinkList List_HeadInsert(LinkList& L) {InitList(L);LNode* s;int x;while (cin >> x) {s = (LNode*)malloc(sizeof(LNode));s->data = x;s->next = L;L = s;}return L;}void print(LinkList L) {LNode* s = L;while (s!= NULL) {cout << s->data << " ";s = s->next;}cout << endl;}}int main() {LinkList L;List_HeadInsert(L);cout << "头插法的结果" << endl;print(L);//List_TailInsert(L);//cout << "尾插法的结果" << endl;//print(L);cout << "链表的第1个元素:" << GetElem(L, 1)->data << endl; cout << "链表的长度:" << Length(L) << endl;int e;ListDelete(L, 5, e);cout << "删除的第1个元素是:" << e << endl;cout << "当前的链表" << endl;print(L);ListInsert(L, 5, e);cout << "插⼊的第1个元素是:" << e << endl;cout << "当前的链表" << endl;print(L);LNode* s = LocateElem(L, 5);return 0;}3.单链表(带头结点)#include<iostream>#include<algorithm>using namespace std;typedef struct LNode {int data;struct LNode* next;}LNode, *LinkList;//struct LNode* == LinkList//强调节点⽤LNode//强调链表⽤LinkList//按位查找,返回第i个元素(带头节点)LNode* GetElem(LinkList L, int i) {if (i < 0) return NULL;int j = 0;LNode* p = L;while (p && j < i) {p = p->next;j++;}return p;}//按值查找,找到数据域等于e的节点LNode* LocateElem(LinkList L, int e) {LNode* p = L->next;while (p && p->data!=e) {p = p->next;}return p;}//统计单链表的长度//统计单链表的长度int Length(LinkList L) {int len = 0;LNode* p = L;while (p->next) {len++;p = p->next;}return len;}//后插操作,在节点p之后插⼊元素ebool InsertNextNode(LNode *p, int e) {if (!p) return false;LNode* s = (LNode*)malloc(sizeof(LNode));if (!s) return false;s->data = e;s->next = p->next;p->next = s;return true;}//带头节点的插⼊操作,在第i个位置插⼊元素ebool ListInsert(LinkList& L, int i, int e) {if (i < 1) return false;LNode* p = GetElem(L, i - 1);if (!p) return false;return InsertNextNode(p, e);}//不带头节点的插⼊操作,在第i个位置插⼊元素ebool NoHead_ListInsert(LinkList& L, int i, int e) {if (i < 1) return false;if (i == 1) {LNode* s = (LNode*)malloc(sizeof(LNode));s->data = e;s->next = L;L = s;return true;}LNode* p;p = L;int j = 1; //当前p指向的是第⼏个节点,没有头节点,所以从1开始 while (p && j < i - 1) {p = p->next;j++;}if (!p) return false;return InsertNextNode(p, e);}//前插操作,在p节点前插⼊元素ebool InsertPriorNode(LNode* p, int e) {if (!p) return false;LNode* s = (LNode*)malloc(sizeof(LNode));if (!s) return false;s->next = p->next;p->next = s;s->data = p->data;p->data = e;return true;}//前插操作,在节点p之前插⼊节点sbool InsertPriorNode(LNode* p, LNode* s) {if ( !p || !s ) return false;if ( !p || !s ) return false;s->next = p->next;p->next = s;swap(s->data , p->data);return true;}//删除位序i的节点,e是i节点的值bool ListDelete(LinkList& L, int i, int& e) {if (i < 1) return false;LNode* p = GetElem(L, i - 1);if (!p || !(p->next)) return false;LNode* q = p->next;e = q->data;p->next = q->next;free(q);return true;}//删除指定节点Pbool DeleteNode(LNode* p) {if (p->next == NULL) return false;//下⾯这段代码有bug,不能删除最后⼀个节点,因此要是删除最后⼀个节点的话要重新进⾏操作 LNode* q = p->next;p->data = q->data;p->next = q->next;free(q);return true;}bool InitList(LinkList& L) {L = (LNode* )malloc(sizeof(LNode));//分配⼀个头节点if (!L) return false;L->next = NULL;return true;}//尾插法,带头结点LinkList List_TailInsert(LinkList& L) {L = (LinkList)malloc(sizeof(LNode));L->next = NULL;LNode* s, * r = L; //r表⽰表尾指针int x;while (cin >> x) {s = (LNode*)malloc(sizeof(LNode));s->data = x;r->next = s;r = s;}r->next = NULL;return L;}//头插法,带头结点LinkList List_HeadInsert(LinkList& L) {L = (LinkList)malloc(sizeof(LNode));L->next = NULL;LNode* s;int x;while (cin >> x) {s = (LNode*)malloc(sizeof(LNode));s->data = x;s->next = L->next;L->next = s;}return L;return L;}void print(LinkList L) {LNode* s = L;while (s->next!=NULL) {s = s->next;cout << s->data << " ";}cout << endl;}int main() {LinkList L;//List_HeadInsert(L);//cout << "头插法的结果" << endl;//print(L);List_TailInsert(L);cout << "尾插法的结果" << endl;print(L);cout << "链表的第2个元素:"<< GetElem(L, 2)->data << endl; cout << "链表的长度:"<< Length(L) << endl;int e;ListDelete(L, 3, e);cout << "删除的第3个元素是:" << e << endl;cout << "当前的链表" << endl;print(L);ListInsert(L, 3, e);cout << "插⼊的第3个元素是:" << e << endl;cout << "当前的链表" << endl;print(L);LNode* s = LocateElem(L, 5);return 0;}3.双链表(带头结点)#include<iostream>using namespace std;typedef int ElemType;typedef struct DNode {ElemType data;struct DNode* prior, * next;}DNode, * DLinkList;//初始化双链表bool InitDLinkList(DLinkList& L) {L = (DNode*)malloc(sizeof(DNode));if (L == NULL) {return false;}L->prior = NULL;L->next = NULL;return true;}//判断双链表是否为空bool empty(DLinkList L) {if (L->next = NULL) {return true;return true;}return false;}//按位查找:返回第i个结点DNode* GetElem(DLinkList L, int i) {if (i < 0) return NULL;int j = 0;DNode* p = L;while (p != NULL && j < i) {p = p->next;j++;}return p;}//按值查找:找到第⼀个数据域为e的结点DNode* LocateElem(DLinkList L, ElemType e) {DNode* p = L;if (p == NULL) return NULL;p = p->next;while (p != NULL && p->data != e) {p = p->next;}return p;}//在p节点之后插⼊s节点bool InsertNextDNode(DNode* p, DNode* s) {if (p == NULL || s == NULL) {return false;}s->next = p->next;if(p->next != NULL)p->next->prior = s;s->prior = p;p->next = s;}//在p节点后⾯插⼊值是e的节点bool InsertNextDNode(DNode* p, ElemType e) {if (p == NULL) return false;DNode* q = (DNode*)malloc(sizeof(DNode));if (q == NULL) return false;q->data = e;q->next = NULL;q->prior = p;if (p->next != NULL) {p->next->prior = q;q->next = p->next;}p->next = q;return true;}//前插,在p节点前⾯插⼊节点sbool InsertPriorDnode(DNode* p, DNode* s) {return InsertNextDNode(p->prior, s);}//按位插⼊,在第i个位置插⼊值为e的节点(位序i)bool InsertDLinkList(DLinkList& L, int i, ElemType e) { if (i <= 0) return false;DNode* p = GetElem(L, i - 1);return InsertNextDNode(p, e);return InsertNextDNode(p, e);}//删除p节点的后继节点bool DeleteNextNode(DNode* p) {if (p == NULL) return false;DNode* q = p->next;if (q == NULL) return false;p->next = q->next;if (q->next != NULL) q->next->prior = p; free(q);return true;}//销毁双链表bool DestoryList(DLinkList& L) {while (L->next != NULL) {DeleteNextNode(L);}free(L);L = NULL;return true;}//尾插法DLinkList List_TailInsert(DLinkList& L) { InitDLinkList(L);DNode* p = L;ElemType x;while (cin >> x) {InsertNextDNode(p, x);p = p->next;}return L;}//头插法DLinkList List_HeadInsert(DLinkList& L) { InitDLinkList(L);ElemType x;while (cin >> x) {InsertNextDNode(L, x);}return L;}int Length(DLinkList L) {DNode* p = L;int len = 0;while (p->next != NULL) {len++;p = p->next;}return len;}//删除指定节点sbool DeleteNode(DNode* s) {DNode* p;p = s->prior;p->next = s->next;if (s->next != NULL) {s->next->prior = p;}free(s);free(s);return true;}//删除位序i的节点,e是i节点的值bool ListDelete(DLinkList& L, int i, ElemType& e) {if (i <= 0 || i > Length(L)) return false;DNode* s;s = GetElem(L, i);if (s == NULL) return false;e = s->data;return DeleteNode(s);}void print(DLinkList L) {DNode* p = L->next;while (p != NULL) {cout << p->data << " ";p = p->next;}cout << endl;}void testDLinkList() {DLinkList L;//cout << "头插法" << endl;//List_HeadInsert(L);//print(L);cout << "尾插法" << endl;List_TailInsert(L);print(L);cout << "长度:" << Length(L) << endl;cout << "第1个元素为:" << GetElem(L, 1)->data << endl; cout << "第5个元素为:" << GetElem(L, 5)->data << endl; cout << "在第⼀个位置插⼊元素0" << endl;InsertDLinkList(L, 1, 0);print(L);cout << "在最后⼀个位置插⼊元素6" << endl;InsertDLinkList(L, 7, 6);print(L);int e;ListDelete(L, 1, e);cout << "删除第⼀个节点:" << e << endl;cout << "当前链表为" << endl;print(L);ListDelete(L, 6, e);cout << "删除最后⼀个节点:" << e << endl;cout << "当前链表为" << endl;print(L);DestoryList(L);}int main() {testDLinkList();return 0;}4.循环单链表(L指向表头)#include<iostream>#include<algorithm>using namespace std;typedef struct LNode {int data;struct LNode* next;}LNode, * LinkList;//struct LNode* == LinkList//强调节点⽤LNode//强调链表⽤LinkListbool InitList(LinkList& L) {L = (LNode*)malloc(sizeof(LNode));//分配⼀个头节点 if (L == NULL) return false;L->next = L;return true;}//按位查找,返回第i个元素(带头节点)LNode* GetElem(LinkList L, int i) {if (i < 0) return NULL;if (i == 0) return L;int j = 1;LNode* p = L->next;while (p != L && j < i) {p = p->next;j++;}return p;}//按值查找,找到数据域等于e的节点LNode* LocateElem(LinkList L, int e) {LNode* p = L->next;while (p != L && p->data != e) {p = p->next;}if (p->data == e) return p;return NULL;}//统计单链表的长度int Length(LinkList L) {int len = 0;LNode* p = L;while (p->next != L) {len++;p = p->next;}return len;}//后插操作,在节点p之后插⼊元素ebool InsertNextNode(LNode* p, int e) {if (!p) return false;LNode* s = (LNode*)malloc(sizeof(LNode));if (!s) return false;s->data = e;s->next = p->next;p->next = s;return true;}//带头节点的插⼊操作,在第i个位置插⼊元素e bool ListInsert(LinkList& L, int i, int e) {if (i < 1) return false;LNode* p = GetElem(L, i - 1);if (!p) return false;return InsertNextNode(p, e);}//前插操作,在p节点前插⼊元素ebool InsertPriorNode(LNode* p, int e) {if (!p) return false;LNode* s = (LNode*)malloc(sizeof(LNode)); if (!s) return false;s->next = p->next;p->next = s;s->data = p->data;p->data = e;return true;}//前插操作,在节点p之前插⼊节点sbool InsertPriorNode(LNode* p, LNode* s) { if (!p || !s) return false;s->next = p->next;p->next = s;swap(s->data, p->data);return true;}//删除位序i的节点,e是i节点的值bool ListDelete(LinkList& L, int i, int& e) {if (i < 1) return false;LNode* p = GetElem(L, i - 1);if (p == NULL || p->next == L) return false; LNode* q = p->next;e = q->data;p->next = q->next;free(q);return true;}//删除指定节点Pbool DeleteNode(LinkList& L, LNode* p) {LNode* q = p->next;p->data = q->data;p->next = q->next;if (L == q) {L = p;}free(q);return true;}//尾插法,带头结点LinkList List_TailInsert(LinkList& L) {InitList(L);LNode* s, * r = L; //r表⽰表尾指针int x;while (cin >> x) {s = (LNode*)malloc(sizeof(LNode));s->data = x;r->next = s;r = s;r = s;}r->next = L;return L;}//头插法,带头结点LinkList List_HeadInsert(LinkList& L) {InitList(L);LNode* s, * r = L;int x;bool isFirst = true;while (cin >> x) {s = (LNode*)malloc(sizeof(LNode));s->data = x;s->next = L->next;L->next = s;if (isFirst) {r = s;isFirst = false;}}r->next = L;return L;}bool Empty(LinkList L) {if (L->next == L) {return true;}return false;}//判断是否为表尾节点bool isTail(LinkList L, LNode* p) {if (p->next == L) return true;return false;}void print(LinkList L) {LNode* s = L->next;while (s != L) {cout << s->data << " ";s = s->next;}cout << endl;}int main() {LinkList L;//List_HeadInsert(L);//cout << "头插法的结果" << endl;//print(L);List_TailInsert(L);cout << "尾插法的结果" << endl;print(L);cout << "链表的第1个元素:" << GetElem(L, 1)->data << endl; cout << "链表的第5个元素:" << GetElem(L, 5)->data << endl; cout << "链表的长度:" << Length(L) << endl;int e;ListDelete(L, 5, e);cout << "删除的第5个元素是:" << e << endl;cout << "当前的链表" << endl;cout << "当前的链表" << endl;print(L);ListInsert(L, 5, e);cout << "插⼊的第5个元素是:" << e << endl;cout << "当前的链表" << endl;print(L);ListDelete(L, 1, e);cout << "删除的第1个元素是:" << e << endl;cout << "当前的链表" << endl;print(L);ListInsert(L, 1, e);cout << "插⼊的第1个元素是:" << e << endl;cout << "当前的链表" << endl;print(L);LNode* s = LocateElem(L, 5);DeleteNode(L, s);print(L);return 0;}/*输⼊样例:1 2 3 4 5*/5.循环单链表(L指向表尾)#include<iostream>#include<algorithm>using namespace std;typedef struct LNode {int data;struct LNode* next;}LNode, * LinkList;//struct LNode* == LinkList//强调节点⽤LNode//强调链表⽤LinkListbool InitList(LinkList& L) {L = (LNode*)malloc(sizeof(LNode));//分配⼀个头节点 if (L == NULL) return false;L->next = L;return true;}//按位查找,返回第i个元素(带头节点)LNode* GetElem(LinkList L, int i) {if (i < 0) return NULL;if (i == 0) return L->next;int j = 1;LNode* p = L->next->next;while (p != L->next && j < i) {p = p->next;j++;}if (p == L->next) return NULL;return p;}//按值查找,找到数据域等于e的节点LNode* LocateElem(LinkList L, int e) {LNode* p = L->next->next;while (p != L->next && p->data != e) {p = p->next;}if (p->data == e) return p;return NULL;}//统计单链表的长度int Length(LinkList L) {int len = 0;LNode* p = L;while (p->next != L) {len++;p = p->next;}return len;}//后插操作,在节点p之后插⼊元素ebool InsertNextNode(LinkList& L, LNode* p, int e) { if (!p) return false;LNode* s = (LNode*)malloc(sizeof(LNode));if (!s) return false;s->data = e;s->next = p->next;p->next = s;if (p == L) L = s;return true;}//带头节点的插⼊操作,在第i个位置插⼊元素e bool ListInsert(LinkList& L, int i, int e) {if (i < 1) return false;LNode* p = GetElem(L, i - 1);if (!p) return false;return InsertNextNode(L, p, e);}//前插操作,在p节点前插⼊元素ebool InsertPriorNode(LNode* p, int e) {if (!p) return false;LNode* s = (LNode*)malloc(sizeof(LNode));if (!s) return false;s->next = p->next;p->next = s;s->data = p->data;p->data = e;return true;}//前插操作,在节点p之前插⼊节点sbool InsertPriorNode(LNode* p, LNode* s) {if (!p || !s) return false;s->next = p->next;p->next = s;swap(s->data, p->data);return true;}//删除位序i的节点,e是i节点的值bool ListDelete(LinkList& L, int i, int& e) {bool ListDelete(LinkList& L, int i, int& e) {if (i < 1) return false;LNode* p = GetElem(L, i - 1);if (p == NULL || p == L) return false;if (p->next == L) {L = p;}LNode* q = p->next;e = q->data;p->next = q->next;free(q);return true;}//删除指定节点Pbool DeleteNode(LinkList& L, LNode* p) {LNode* q = p->next;p->data = q->data;p->next = q->next;if (L == p) { //尾节点q = p;while (q->next != p) {q = q->next;}L = q;}//free(q);不能这样写,因为指针之间的赋值是指向同⼀块区域,就⽐如L和q就是指向相同的区域 return true;}//尾插法,带头结点LinkList List_TailInsert(LinkList& L) {InitList(L);LNode* s, * r = L; //r表⽰表尾指针int x;while (cin >> x) {s = (LNode*)malloc(sizeof(LNode));s->data = x;r->next = s;r = s;}r->next = L;L = r;return L;}//头插法,带头结点LinkList List_HeadInsert(LinkList& L) {InitList(L);LNode* s, * r = L;int x;bool isFirst = true;while (cin >> x) {s = (LNode*)malloc(sizeof(LNode));s->data = x;s->next = L->next;L->next = s;if (isFirst) {r = s;isFirst = false;}}r->next = L;L = r;L = r;return r;}bool Empty(LinkList L) {if (L->next == L) {return true;}return false;}//判断是否为表尾节点bool isTail(LinkList L, LNode* p) {if (p == L) return true;return false;}void print(LinkList L) {LNode* s = L->next->next;while (s != L->next) {cout << s->data << " ";s = s->next;}cout << endl;}int main() {LinkList L;//List_HeadInsert(L);//cout << "头插法的结果" << endl;//print(L);List_TailInsert(L);cout << L->data << endl;cout << "尾插法的结果" << endl;print(L);cout << "链表的第1个元素:" << GetElem(L, 1)->data << endl; cout << "链表的第5个元素:" << GetElem(L, 5)->data << endl; cout << "链表的长度:" << Length(L) << endl;int e;ListDelete(L, 5, e);cout << "删除的第5个元素是:" << e << endl;cout << "当前的链表" << endl;print(L);ListInsert(L, 5, e);cout << "插⼊的第5个元素是:" << e << endl;cout << "当前的链表" << endl;print(L);ListDelete(L, 1, e);cout << "删除的第1个元素是:" << e << endl;cout << "当前的链表" << endl;print(L);ListInsert(L, 1, e);cout << "插⼊的第1个元素是:" << e << endl;cout << "当前的链表" << endl;print(L);LNode* s = LocateElem(L, 5);DeleteNode(L, s);print(L);return 0;}}/*输⼊样例:1 2 3 4 5*/6.循环双链表#include<iostream>using namespace std;typedef int ElemType;typedef struct DNode {ElemType data;struct DNode* prior, * next;}DNode, * DLinkList;//初始化双链表bool InitDLinkList(DLinkList& L) {L = (DNode*)malloc(sizeof(DNode));if (L == NULL) {return false;}L->prior = L;L->next = L;return true;}//判断双链表是否为空bool empty(DLinkList L) {if (L->next = L) {return true;}return false;}bool isTail(DLinkList L, DNode* p) {if (p->next == L) return true;return false;}//按位查找:返回第i个结点DNode* GetElem(DLinkList L, int i) {if (i < 0) return NULL;if (i == 0) return L;int j = 1;DNode* p = L->next;while (p != L && j < i) {p = p->next;j++;}if (p == L) return NULL;return p;}//按值查找:找到第⼀个数据域为e的结点DNode* LocateElem(DLinkList L, ElemType e) { DNode* p = L;if (p == NULL) return NULL;p = p->next;while (p != L && p->data != e) {p = p->next;}if (p == L) return NULL;return p;}//在p节点之后插⼊s节点bool InsertNextDNode(DNode* p, DNode* s) {if (p == NULL || s == NULL) {return false;}s->next = p->next;p->next->prior = s;s->prior = p;p->next = s;}//在p节点后⾯插⼊值是e的节点bool InsertNextDNode(DNode* p, ElemType e) {if (p == NULL) return false;DNode* q = (DNode*)malloc(sizeof(DNode));if (q == NULL) return false;q->data = e;q->prior = p;p->next->prior = q;q->next = p->next;p->next = q;return true;}//前插,在p节点前⾯插⼊节点sbool InsertPriorDnode(DNode* p, DNode* s) {return InsertNextDNode(p->prior, s);}//按位插⼊,在第i个位置插⼊值为e的节点(位序i)bool InsertDLinkList(DLinkList& L, int i, ElemType e) { if (i <= 0) return false;DNode* p = GetElem(L, i - 1);return InsertNextDNode(p, e);}//删除p节点的后继节点bool DeleteNextNode(DNode* p) {if (p == NULL) return false;DNode* q = p->next;p->next = q->next;q->next->prior = p;free(q);return true;}//销毁双链表bool DestoryList(DLinkList& L) {while (L->next != L) {DeleteNextNode(L);}free(L);L = NULL;return true;}//尾插法DLinkList List_TailInsert(DLinkList& L) {InitDLinkList(L);ElemType x;while (cin >> x) {InsertNextDNode(p, x);p = p->next;}return L;}//头插法DLinkList List_HeadInsert(DLinkList& L) {InitDLinkList(L);ElemType x;while (cin >> x) {InsertNextDNode(L, x);}return L;}int Length(DLinkList L) {DNode* p = L;int len = 0;while (p->next != L) {len++;p = p->next;}return len;}//删除指定节点sbool DeleteNode(DNode* s) {DNode* p;p = s->prior;p->next = s->next;s->next->prior = p;free(s);return true;}//删除位序i的节点,e是i节点的值bool ListDelete(DLinkList& L, int i, ElemType& e) { if (i <= 0 || i > Length(L)) return false;DNode* s;s = GetElem(L, i);if (s == NULL) return false;e = s->data;return DeleteNode(s);}void print(DLinkList L) {DNode* p = L->next;while (p != L) {cout << p->data << " ";p = p->next;}cout << endl;}void testDLinkList() {DLinkList L;//cout << "头插法" << endl;//List_HeadInsert(L);//print(L);cout << "尾插法" << endl;。
408考稀疏矩阵十字链表
408考稀疏矩阵十字链表稀疏矩阵是指矩阵中绝大部分元素为0的情况下,只存储非零元素及其位置信息的一种存储方式。
在计算机科学中,稀疏矩阵的存储方式有多种,其中一种较为常见的方式是使用十字链表。
十字链表是一种基于链表的数据结构,用于表示稀疏矩阵。
它通过两个链表和一个头节点来表示稀疏矩阵的行和列。
具体来说,十字链表由以下几个部分组成:1. 头节点:头节点用于存储稀疏矩阵的行数、列数和非零元素的个数等基本信息。
2. 行链表:行链表由多个节点组成,每个节点代表稀疏矩阵的一行。
每个节点包含三个属性:行号、列号和值。
行链表按照行号从小到大的顺序排列。
3. 列链表:列链表由多个节点组成,每个节点代表稀疏矩阵的一列。
每个节点包含三个属性:行号、列号和值。
列链表按照列号从小到大的顺序排列。
4. 节点链接:行链表和列链表中的节点通过行号和列号进行链接。
对于每个节点,除了存储自身的行号、列号和值外,还需存储其所在行的下一个节点和所在列的下一个节点。
使用十字链表来存储稀疏矩阵的好处是可以大大减少存储空间的使用,尤其适用于稀疏矩阵中非零元素的个数相对较少的情况。
通过十字链表,我们可以快速访问稀疏矩阵中的非零元素,并且可以方便地进行行和列的插入、删除和修改操作。
下面举一个具体的例子来说明408考稀疏矩阵十字链表的应用。
假设有一个3行4列的稀疏矩阵,其中非零元素分别为6、8、9、7,它们的位置分别是(1, 2)、(2, 1)、(2, 3)、(3, 4)。
我们可以使用十字链表来表示这个稀疏矩阵。
我们创建一个头节点,存储稀疏矩阵的行数、列数和非零元素的个数,即3、4和4。
然后,我们创建4个节点,分别表示这4个非零元素。
这些节点的属性分别为:(1, 2, 6)、(2, 1, 8)、(2, 3, 9)和(3, 4, 7)。
同时,我们需要将这些节点链接到行链表和列链表中相应的位置。
在行链表中,我们将这些节点按照行号从小到大的顺序插入。
首先,我们插入节点(1, 2, 6),因为它的行号最小。
图——数据结构逆邻接表与十字链表
图——数据结构逆邻接表与⼗字链表前⾔:如果你已经学习了邻接表的存储思想,那么逆邻接表也⾮常好理解,我们的重点是⼗字链表 ⾸先我们来继续介绍逆邻接表,逆邻接表和邻接表是⼀样的,只不过在邻接表上,⼀个顶点后⾯连接的⼀串节点都是以顶点为弧尾的弧头节点,我们建⽴邻接表的时候就先查找⼀条边的起点,然后往这个起点上连接新的顶点,那么逆邻接表就是反过来,逆邻接表中⼀个顶点后⾯的⼀串节点都是以顶点为弧头的弧尾节点,我们建⽴逆邻接表的时候,先查找⼀条边的终点,然后往这个重点上连接包含起点信息的节点; 逆邻接表就介绍到这⾥,下⾯我们介绍⼗字链表,⾸先我们抛出这样⼀句话,⼗字链表是正邻接表和逆邻接表的合体,然后我们再介绍这样⼀个观念,我们在逆邻接表或者邻接表中所提到的节点,其实可以理解为弧节点,弧节点可以包含弧头顶点在图中的位置(我们在正邻接表中遇到的),也可以包含弧尾顶点在图中的位置(逆邻接表);下⾯我们给出具体的例⼦帮助⼤家理解 现在思考下当我们要建⽴⼗字链表时会发⽣些什么:⾸先我们建⽴好顶点数组,和在邻接表中的⼀样,然后呢,我们开始添加 e01 这个边,或者说弧现在我们要⽤弧节点的思路去理解他,如何添加这个弧,这个弧包含了哪些信息?弧包含了tail,代表弧尾表⽰的顶点在图中的位置,也就是这个弧是由谁发射出来的,head呢,表⽰这个弧指向了谁,同样储存的是顶点在顶点数组中的索引;后⾯这两项是地址,是什么类型的地址呢,这个地址指向的空间要放什么东西呢,放的仍然是弧节点,但是这两个地址所放的不是同⼀个弧节点,这个tlink,指向的是下⼀个弧节点,tlink指向的这个弧节点的弧尾和tlink所在的弧的弧尾是相同的,按照这样的想法,我们很容易想到沿着tlink⼀路⾛下去,我们就可以遍历由同⼀个顶点发射的所有弧,相当于是⼀个正邻接表,同理沿着hlink我们会遍历指向同⼀个顶点的所有弧,⽽⼀个弧节点既有hlink,⼜有tlink,所以正邻接表和逆邻接表是交叉的,这就叫做⼗字链表, 那么如何来具体的建⽴⼀个⼗字链表呢,回顾上⼀节我们提到的,先建⽴顶点数组,然后按照⽤户输⼊的边去建⽴弧节点,然后给弧节点填充相应的信息,再把弧节点链接到已有的⼗字链表上,链接的时候⼜需要分情况,我这个弧节点是不是处于邻接表的第⼀个或者是逆邻接表的第⼀个,如果是的话,需要操作顶点的firstin或者firstout,如果不是的话需要操作”最后⼀个“弧节点,那么这⾥和上⼀节的操作⼀样,我们仍然需要去标记⼀下”最后⼀个弧节点“,只不过这⾥不仅要标记正邻接表的最后⼀个弧节点,还需要标记逆邻接表中处于最后⼀个的弧节点, 如此如此这番这番,思路就跃然纸上了(具体化了),下⾯我们给出具体代码,并针对上⼀节中,判定是否⼀个顶点没有弧节点相连(⼗字链表中其实是没有正邻接表‘也就是弧尾’或逆邻接表‘也就是弧头’相连,或者两个都没有)的判定进⾏了更正;1//验证图的⼗字链表存储2 #include <stdio.h>3 #include <windows.h>4#define vexNum 1056 typedef struct ArcNode7 {8//索引9int tailVex;10int headVex;1112//地址,按照tlink,可以⼀路遍历完正邻接表13struct ArcNode *tlink;14struct ArcNode *hlink;1516//info代表弧的权重17int info;1819 } ArcNode;2021 typedef struct VexNode22 {23char data;24 ArcNode *last1End; //正邻接表的最后⼀个弧节点25 ArcNode *last2End; //逆邻接表的最后⼀个弧节点26 ArcNode *second1; //正、第⼀个弧节点27 ArcNode *second2; //逆、第⼀个弧节点28 } VexNode;2930 typedef struct graph31 {32int vexN;33int edgeN;34 VexNode adjList[vexNum];35 } graph;3637//寻找顶点在图中的位置38int locatVex(char vex, graph g)39 {40int i = 0;41for (i; i < g.vexN; i++)42 {43if (vex == g.adjList[i].data)44 {45return i;46 }47 }48return -1;49 }50void creatOLGraph(graph *g)51 {52 printf("请输⼊节点数和边数:\n");53 scanf("%d %d", &g->vexN, &g->edgeN);54 getchar();55 printf("请输⼊节点数组,不带空格\n");56int i = 0;57for (i; i < g->vexN; i++)58 {59 scanf("%c", &g->adjList[i].data);60 g->adjList[i].second1 = NULL;61 g->adjList[i].second2 = NULL;62 g->adjList[i].last1End = NULL;63 g->adjList[i].last2End = NULL;64 }65 getchar();66 printf("请输⼊边:\n");6768int v1, v2;69char vv1, vv2;70for (i = 0; i < g->edgeN; i++)71 {72 scanf("%c %c", &vv1, &vv2);73 getchar();74 v1 = locatVex(vv1, *g);75 v2 = locatVex(vv2, *g);76 ArcNode *p;77 p = (ArcNode *)malloc(sizeof(ArcNode));7879//同⼀个弧节点,先对正邻接表操作,再对逆邻接表操作8081//弧节点的弧尾是v182 p->tailVex = v1;83if (g->adjList[v1].last1End == NULL)84 {85//顶点的第⼀个弧节点是p,该顶点正邻接表的最后⼀个弧节点也是p86 g->adjList[v1].second1 = p;87 g->adjList[v1].last1End = p;88 }89else90 {91//向正邻接表中添加⼀个元素,92 g->adjList[v1].last1End->tlink = p;93 g->adjList[v1].last1End = p;94 }9596 p->headVex = v2;97if (g->adjList[v2].last2End == NULL)98 {99 g->adjList[v2].second2 = p;100 g->adjList[v2].last2End = p;101 }102else103 {104 g->adjList[v2].last1End->hlink = p;105 g->adjList[v2].last1End = p;106 }107 }108 }109110int main()111 {112 graph g;113 creatOLGraph(&g);114//验证⼗字链表的存储115int i = 0;116for (i; i < g.vexN; i++)117 {118 ArcNode *show;119//之前我们做判断,是判断“最后⼀个节点”是否为顶点,现在我们更改了初始化条件,把之前的初始化为顶点地址改成了初始化为NULL这就避免了类型不兼容的警告120if (g.adjList[i].last2End != NULL)121 {122 printf("发往%c的弧,弧尾是 ", g.adjList[i].data);123 show = g.adjList[i].second2;124while (show != g.adjList[i].last2End)125 {126 printf("%c、", g.adjList[show->tailVex].data);127 show = show->hlink;128 }129 printf("%c\n", g.adjList[show->tailVex].data);130 }131132if (g.adjList[i].last1End != NULL)133 {134 printf("由%c发出的弧的弧头是 ", g.adjList[i].data);135 show = g.adjList[i].second1;136while (show != g.adjList[i].last1End)137 {138 printf("%c、", g.adjList[show->headVex].data);139 show = show->tlink;140 }141 printf("%c\n", g.adjList[show->headVex].data);142 }143 }144 system("pause");145return0;146 }参考:《新编数据结构案例教程(C/C++)版》薛晓亚主编。
(原创)数据结构之十字链表总结
(原创)数据结构之⼗字链表总结7-1 稀疏矩阵(30 分)如果⼀个矩阵中,0元素占据了矩阵的⼤部分,那么这个矩阵称为“稀疏矩阵”。
对于稀疏矩阵,传统的⼆维数组存储⽅式,会使⽤⼤量的内存来存储0,从⽽浪费⼤量内存。
为此,可以⽤三元组的⽅式来存放⼀个稀疏矩阵。
对于⼀个给定的稀疏矩阵,设第r⾏、第c列值为v,且v不等于0,则这个值可以表⽰为 <r,v,c>。
这个表⽰⽅法就称为三元组。
那么,对于⼀个包含N个⾮零元素的稀疏矩阵,就可以⽤⼀个由N个三元组组成的表来存储了。
如:{<1, 1, 9>, <2, 3, 5>, <10, 20, 3>}就表⽰这样⼀个矩阵A:A[1,1]=9,A[2,3]=5,A[10,20]=3。
其余元素为0。
要求查找某个⾮零数据是否在稀疏矩阵中,如果存在则输出其所在的⾏列号,不存在则输出ERROR。
输⼊格式:共有N+2⾏输⼊:第⼀⾏是三个整数m, n, N(N<=500),分别表⽰稀疏矩阵的⾏数、列数和矩阵中⾮零元素的个数,数据之间⽤空格间隔; 随后N⾏,输⼊稀疏矩阵的⾮零元素所在的⾏、列号和⾮零元素的值;最后⼀⾏输⼊要查询的⾮0数据k。
输出格式:如果存在则输出其⾏列号,不存在则输出ERROR。
输⼊样例:在这⾥给出⼀组输⼊。
例如:10 29 32 18 -107 1 988 10 22输出样例:在这⾥给出相应的输出。
例如:8 10解题思路:实际上这道题⽤三元组写轻松解决,但是这⾥想讲的是⼗字链表;⼗字链表的图⼤致如下:那么如何去实现呢;看以下代码:因为下⾯都有注释,这⾥便不赘述了。
1 #include<iostream>2 #include<stdio.h>3using namespace std;45struct OLNod{6int i ; //该⾮零元的⾏下标;7int j ; //该⾮零元的列下标;8int value ; //该⾮零元的数值;9struct OLNod *right ,*down ;//该⾮零元所在的⾏表和列表的后继链域;10 };11struct CrossL{12 OLNod **rhead, **sead;13//⼗字链表的⾏头指针和列头指针;定义为指向指针的指针;14int row; //稀疏矩阵的⾏数;15int col; //稀疏矩阵的列数;16int num; //稀疏矩阵的⾮零个数;17 };1819int InitSMatrix(CrossL *M) //初始化M(CrossL)类型的变量必须初始化;20 {21 (*M).rhead = (*M).sead = NULL;22 (*M).row = (*M).col = (*M).num = 0;23return1;24 }2526int DestroysMatrix(CrossL *M) //销毁稀疏矩阵M;27 {28int i ;29 OLNod *p,*q;30for( i = 1 ; i <= (*M).row;i++)31 {32 p = *((*M).rhead+i); //p指针不断向右移;33while(p!=NULL)34 {35 q = p ;36 p = p ->right;37delete q; //删除q;38 }39 }40delete((*M).rhead); //释放⾏指针空间;41delete((*M).sead); //释放列指针空间;42 (*M).rhead = (*M).sead = NULL; //并将⾏、列头指针置为空;43 (*M).num = (*M).row = (*M).col = 0; //将⾮零元素,⾏数和列数置为0; 44return1;45 }46int CreatSMatrix(CrossL *M)47 {48int i , j , m , n , t;49int value;50 OLNod *p,*q;51if((*M).rhead!=NULL)52 DestroysMatrix(M);53 cin>>m>>n>>t; //输⼊稀疏矩阵的⾏数、列数和⾮零元个数;54 (*M).row = m;55 (*M).col = n ;56 (*M).num = t;57//初始化⾏链表头;58 (*M).rhead = new OLNod*[m+1];//为⾏头指针申请⼀个空间;59if(!(*M).rhead) //如果申请不成功,则退出程序;60 exit(0);61//初始化列链表头;62 (*M).sead = new OLNod*[n+1];//为列表头申请⼀个空间;63if(!(*M).sead) //如果申请不成功,则退出程序;64 exit(0);65for(int k = 1 ; k <= m ; k++)66 {67 (*M).rhead[k] = NULL;//初始化⾏头指针向量;各⾏链表为空链表;68 }69for(int k = 1 ; k <= n ;k++)70 {71 (*M).sead[k] = NULL;//初始化列头指针向量;各列链表为空链表;72 }73for(int k = 0 ; k < t ;k++) //输⼊⾮零元素的信息;74 {75 cin>>i>>j>>value;//输⼊⾮零元的⾏、列、数值;76 p = new OLNod();//为p指针申请⼀个空间;77if(!p) //e如果申请不成功;78 exit(0); //退出程序;79 p->i = i;80 p->j = j;81 p->value = value;82if((*M).rhead[i]==NULL) //如果⾏头指针指向的为空;83 {84//p插在该⾏的第⼀个结点处;85 p->right = (*M).rhead[i];86 (*M).rhead[i] = p;87 }else//如果不指向空88 {89for(q = (*M).rhead[i];q->right; q = q->right);90 p->right = q->right;91 q->right = p;9293 }94if((*M).sead[j]==NULL)//如果列头指针指向的为空;95 {96//p插在该⾏的第⼀个结点处;97 p->down = (*M).sead[j];98 (*M).sead[j] = p;99 }else//如果不指向空100 {101for(q = (*M).sead[j];q->down;q = q->down);102 p->down = q->down;103 q->down = p;104 }105 }106return1;107 }108int PrintSMatrix(CrossL *M)109 {110int flag = 0;111int val ;//要查找的元素的值;112 cin>>val; //输⼊要查找的s值;113 OLNod *p;114for(int i = 1 ; i <= (*M).row ;i++)115 {116for(p = (*M).rhead[i];p;p = p->right) //从⾏头指针开始找,不断向右找117 {118if(p->value==val) //如果能找到119 {120 cout<<p->i<<""<<p->j; //输出⾏下标和列下标121 flag = 1; //标记找到该元素;122 }123 }124 }125126127if(flag==0) //如果找不到128 {129 cout<<"ERROR\n";130 }131132 }133int main()134 {135 CrossL A; //定义⼀个⼗字链表;136 InitSMatrix(&A); //初始化;137 CreatSMatrix(&A); //创建;138 PrintSMatrix(&A); //输出;139 DestroysMatrix(&A); //销毁;140return0;141 }。
数据结构第7章-答案
一、单选题C01、在一个图中,所有顶点的度数之和等于图的边数的倍。
A)1/2 B)1 C)2 D)4B02、在一个有向图中,所有顶点的入度之和等于所有顶点的出度之和的倍。
A)1/2 B)1 C)2 D)4B03、有8个结点的无向图最多有条边。
A)14 B)28 C)56 D)112C04、有8个结点的无向连通图最少有条边。
A)5 B)6 C)7 D)8C05、有8个结点的有向完全图有条边。
A)14 B)28 C)56 D)112B06、用邻接表表示图进行广度优先遍历时,通常是采用来实现算法的。
A)栈 B)队列 C)树 D)图A07、用邻接表表示图进行深度优先遍历时,通常是采用来实现算法的。
A)栈 B)队列 C)树 D)图A08、一个含n个顶点和e条弧的有向图以邻接矩阵表示法为存储结构,则计算该有向图中某个顶点出度的时间复杂度为。
A)O(n) B)O(e) C)O(n+e) D)O(n2)C09、已知图的邻接矩阵,根据算法思想,则从顶点0出发按深度优先遍历的结点序列是。
A)0 2 4 3 1 5 6 B)0 1 3 6 5 4 2 C)0 1 3 4 2 5 6 D)0 3 6 1 5 4 2B10、已知图的邻接矩阵同上题,根据算法,则从顶点0出发,按广度优先遍历的结点序列是。
A)0 2 4 3 6 5 1 B)0 1 2 3 4 6 5 C)0 4 2 3 1 5 6 D)0 1 3 4 2 5 6D11、已知图的邻接表如下所示,根据算法,则从顶点0出发按深度优先遍历的结点序列是。
A)0 1 3 2 B)0 2 3 1 C)0 3 2 1 D)0 1 2 3A12、已知图的邻接表如下所示,根据算法,则从顶点0出发按广度优先遍历的结点序列是。
A)0 3 2 1 B)0 1 2 3 C)0 1 3 2 D)0 3 1 2A13、图的深度优先遍历类似于二叉树的。
A)先序遍历 B)中序遍历 C)后序遍历 D)层次遍历D14、图的广度优先遍历类似于二叉树的。
数据结构-图的定义和术语
继续进行 ·3
·4
搜索。
·5
·6
·7
·3 ·1
·2
·4 从结点 5 出发的搜索序列:
5、6、2、3、1、4、7 适用的数据结构:栈
图的遍历
2、广度(宽度)优先搜索:
• 树:
A
B
C
D
EFG H
I JK
树的按层次进行访问的次序: A、B、C、D、E、F、G、H、 I、J、K、L
适用的数据结构:队列
L A
1
·1
2
12
11
·2
·11
·12
3
6
7
10
·3 ·6 ·7
·10
4
5
8
9
·4 ·5 ·8
·9
图的广度优先的访问次序:
1、2、11、12、3、6、7、10、4、5、8、9
适用的数据结构:队列
图的连通性问题
2、有向图的强连通分量的求法:续 •强连通分量的求法:
1、对有向图 G 进行深度为主的搜索,按照退 出该结点的次序给结点进行编号。最先退 出的结点的编号为 1,其它结点的编号按 次序逐次增大 1。
点1
3 已在U中
16 21 35
0 0 0
lowcost 表示最小距离
4∞ 0
adjvex 表示相应结点(在V -U中的)
5∞
0
lowcost adjvex
U1
6
5 1
25 35 4
3
6
4
2
566 图G
数组:closedge[ 6 ]
00 15 2 20 35 0 46 2 54 2
lowcost adjvex
邻接表十字链表
(续) for(i=0;i<G->vexnum;i++) printf("%4d",i); printf("\n"); for(i=0;i<G->vexnum;i++) { printf("%6d",i); for(j=0;j<G->vexnum;j++) printf("%4d",G->edges[i][j]);
A B A B
C
D
C
D
图7.6 G2的两棵生成树
例7.1 有n个顶点的连通图最多有多少条边? 最少应多少条边? 解:有n个顶点的连通图最多有n(n-1)/2条 边,也就是一个无向完全图;最少有n-1条 边。
7.2 图的存储结构
图的存储结构除存储图中各个顶点本身 的信息外,同时还要存储顶点之间的所 有关系。图的常用存储结构有邻接矩阵、 邻接表、十字链表。
7.2.1
邻接矩阵
设G=(V,E)是具有n(n>0)个顶点的图,顶 点的顺序依次为(v0,v1,…,vn-1),则 G的邻接矩阵A是n阶方阵,其定义如下: (1) 如果G是无向图,则:
1, 若(vi , v j ) E (G ) A[i ][ j ] 0, 其它
(2) 如果G是有向图,则:
邻接表的头结点和表结点的结构如下:
data
firstarc
adjvex
nextarc
info
头结点
表结点
如图7.8(a)和(b)所示分别为图G1和图G2的 邻接表。
0 1 2 3
A B C D /\ 3 0 /\ /\ 2 1 /\
十字链表法
十字链表法十字链表(又称叉链表)是一种利用数据链表技术实现图表表示的数据结构。
一般来说,它由两个基本结构:一个表示节点的字表和一个表示节点之间联系的叉链表组成,利用叉链表的特点,可以把一个复杂的图/网表结构以一种更简单的方式表示出来,并且可以应用在不同的任务上。
十字链表的结构非常类似。
它有一个头节点,每个节点都包含两个指针:一个指向表头,一个指向该节点的父节点,以及一个指向该节点的子节点。
字表则用于保存该节点的相关数据,其中包括该节点的事件,以及与之关联的其它数据。
###字链表在数据处理中的应用十字链表法可以应用在多种情况中,用于快速查找、修改,以及处理复杂的数据结构。
它比其它常见的数据存取方法更加有效率,因为它可以非常快速地找到数据的父节点和子节点。
例如,在图结构存储中,当我们需要查找一个特定的节点时,我们可以使用十字链表法快速找到,因为它的优势是它可以基于每个节点的父子关系查找所有相关的节点和数据。
另外,十字链表法也可以用于实现事件驱动系统,当用户改变某个图表中的内容时,系统可以根据这些内容的变化,快速地更新数据结构中的关系。
例如,当用户添加一个节点时,系统就可以立即将其添加到十字链表中,以此达到实时更新的目的。
此外,还可以利用十字链表来实现复杂的搜索引擎,允许用户快速搜索数据库中的指定内容。
一个典型的例子是满足多个条件的数据,十字链表可以极大地减少搜索的范围。
###字链表的优势首先,十字链表可以更有效地存储图形网络结构和复杂数据结构,它可以把这些复杂的结构转换成更简单的表示形式,从而使得可以更快地查找和处理这些数据。
其次,十字链表的插入和删除操作也较快,它可以把节点从一个位置转移到另一个位置,而不会增加其它操作的次数。
最后,十字链表法的另一个特点是可以很容易地实现多处理器的数据处理,这意味着它可以被用来在同一时间处理多个数据流。
###论虽然十字链表法在某些情况下并不直观,但它却可以帮助我们快速查找和处理复杂的数据结构。
数据结构完整代码
(线性表顺序存储)#include"string.h"#include"ctype.h"#include"stdio.h"#include"stdlib.h"#include"io.h"#include"math.h"#include"time.h"#define OK1#define ERROR0#define TRUE1#define FALSE0#define MAXSIZE20/*存储空间初始分配量*/ typedef int Status;/*Status是函数的类型,其值是函数结果状态代码,如OK等*/typedef int ElemType;/*ElemType类型根据实际情况而定,这里假设为int*/Status visit(ElemType c){printf("%d",c);return OK;}typedef struct{ElemType data[MAXSIZE];/*数组,存储数据元素*/int length;/*线性表当前长度*/}SqList;/*初始化顺序线性表*/Status InitList(SqList*L){L->length=0;return OK;}/*初始条件:顺序线性表L已存在。
操作结果:若L为空表,则返回TRUE,否则返回FALSE*/Status ListEmpty(SqList L){if(L.length==0)return TRUE;elsereturn FALSE;}/*初始条件:顺序线性表L已存在。
操作结果:将L重置为空表*/Status ClearList(SqList*L){L->length=0;return OK;}/*初始条件:顺序线性表L已存在。
操作结果:返回L 中数据元素个数*/int ListLength(SqList L){return L.length;}/*初始条件:顺序线性表L已存在,1≤i≤ListLength(L)*/ /*操作结果:用e返回L中第i个数据元素的值,注意i 是指位置,第1个位置的数组是从0开始*/Status GetElem(SqList L,int i,ElemType*e){if(L.length==0||i<1||i>L.length)return ERROR;*e=L.data[i-1];return OK;}/*初始条件:顺序线性表L已存在*//*操作结果:返回L中第1个与e满足关系的数据元素的位序。
数据结构链表简单程序代码
display(L);
printf("\n");
insert(&L,2,6);//在第2个位置插入元素6
printf("在第2个位置插入6后的链表为:");//显示插入元素后的链表
display(L);
printf("\n");
q->next=L->next;// 在表头节点
L->next=q; // 后插入节点,且每次插入的都是后移后的节点
}
}
//链表长度函数
int length(Lnode L)
{
return L.len;
}
//插入元素函数
void insert(Lnode *L,int i,elemtype x)
}
creatlist(&L);//创建空链表
for(i=0;i<n;i++)//把元素放入链表
{
putlist(&L,a[i]);
}
printf("数入链表为:");//显示输入的链表
display(L);
printf("\n");
converse(&L);//逆置链表
{
j++;
if(j==i+1)break;//因为有头结点,所以是i+1
p=p->next;
}
return p->data;//返回第i个元素的值
}
//删除元素函数
C数据结构实例代码
C数据结构实例代码C语言是一种通用的高级程序设计语言,也是实现数据结构的一种常用语言。
下面是一些常见的数据结构的示例代码,供参考。
1. 数组(Array)```c#include <stdio.h>int maiint arr[5] = {1, 2, 3, 4, 5}; // 创建一个有5个元素的整数数组for(int i=0; i<5; i++)printf("%d ", arr[i]); // 遍历并输出数组的所有元素}return 0;```2. 链表(Linked List)```c#include <stdio.h>#include <stdlib.h>struct Nodeint data;struct Node* next;};void printList(struct Node* head)struct Node* curr = head;while(curr != NULL)printf("%d ", curr->data);curr = curr->next;}void insert(struct Node** head, int data)struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));newNode->data = data;newNode->next = (*head);(*head) = newNode;int maistruct Node* head = NULL;insert(&head, 5);insert(&head, 4);insert(&head, 3);insert(&head, 2);insert(&head, 1);printList(head); // 输出链表的所有元素return 0;```3. 栈(Stack)```c#include <stdio.h>#define SIZE 5int stack[SIZE];int top = -1;int isEmptreturn top == -1;int isFulreturn top == SIZE - 1;void push(int item)if(isFull()printf("Stack is full.\n");} elsestack[++top] = item;printf("Pushed %d\n", item);}void poif(isEmpty()printf("Stack is empty.\n");} elseprintf("Popped %d\n", stack[top--]); }int maipush(1);push(2);push(3);pop(;push(4);push(5);push(6);pop(;return 0;```4. 队列(Queue)```c#include <stdio.h>#define SIZE 5int queue[SIZE];int front = -1; // 队头指针int rear = -1; // 队尾指针int isEmptreturn front == -1 && rear == -1; int isFulreturn rear == SIZE - 1;void enqueue(int item)if(isFull()printf("Queue is full.\n");} elseif(isEmpty()front = rear = 0;} elserear++;}queue[rear] = item;printf("Enqueued %d\n", item);}void dequeuif(isEmpty()printf("Queue is empty.\n");} elseprintf("Dequeued %d\n", queue[front]); if(front == rear)front = rear = -1;} elsefront++;}}int maienqueue(1);enqueue(2);enqueue(3);dequeue(;enqueue(4);enqueue(5);enqueue(6);dequeue(;return 0;```5. 树(Tree)```c#include <stdio.h>#include <stdlib.h>struct Nodeint data;struct Node* left;struct Node* right;};struct Node* create(int data)struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));newNode->data = data;newNode->left = NULL;newNode->right = NULL;return newNode;void inorder(struct Node* root)if(root != NULL)inorder(root->left);printf("%d ", root->data);inorder(root->right);}int maistruct Node* root = create(1);root->left = create(2);root->right = create(3);root->left->left = create(4);root->left->right = create(5);root->right->left = create(6);root->right->right = create(7);printf("Inorder traversal of the tree: "); inorder(root); // 中序遍历树return 0;```。
数据结构代码汇总
数据结构代码汇总数据结构代码汇总一、线性结构1.数组(Array):●定义和初始化数组●插入、删除元素●查找元素●数组的遍历●数组排序算法(如冒泡排序、快速排序)2.链表(Linked List):●单链表的定义和初始化●插入、删除节点●链表的遍历●双向链表的定义和初始化●插入、删除节点●双向链表的遍历●栈的定义和初始化●入栈、出栈操作●获取栈顶元素、判断栈是否为空●栈的应用(如括号匹配、逆波兰表达式求值)4.队列(Queue):●队列的定义和初始化●入队、出队操作●获取队头元素、判断队列是否为空●队列的应用(如循环队列、优先级队列)二、非线性结构1.树(Tree):●二叉树的定义和初始化●二叉树的遍历(前序、中序、后序)●二叉搜索树的实现和应用●平衡二叉树(AVL树)的实现和应用●哈夫曼树的实现和应用●图的存储结构(邻接矩阵、邻接表)●深度优先搜索(DFS)●广度优先搜索(BFS)●最小树算法(如Prim算法、Kruskal算法)●最短路径算法(如Dijkstra算法、Floyd算法)附件:本文档中所涉及的代码示例可以在附件中找到,包括各种数据结构的实现和相关算法。
法律名词及注释:1.数组:计算机科学中的一种数据结构,用于存储一系列相同类型的元素。
2.链表:一种动态数据结构,由一系列节点组成,每个节点包含一个数据元素和指向下一个节点的指针。
3.栈:一种特殊的线性数据结构,遵循先进后出(Last In First Out,LIFO)的原则。
4.队列:一种特殊的线性数据结构,遵循先进先出(First In First Out,FIFO)的原则。
5.二叉树:一种特殊的树形结构,每个节点最多有两个子节点。
6.图:由节点(顶点)和连接节点的边构成的数据结构,用于描述事物之间的关系。
考研《数据结构》考试大纲
理工大学2020年硕士学位研究生招生考试业务课考试大纲考试科目:数据结构代码:991考试的总体要求考查学生对数据的逻辑结构和物理结构的基本概念的掌握,对基本的数据结构和算法的掌握;考查学生利用基本数据结构和算法,使用C语言来解决实际科学和理论问题的思想和能力。
基本内容一、线性表1.线性表的概念及特点2.线性表的逻辑结构3.线性表的顺序及链式存储结构4.相关的各种基本运算二、栈和队列1.栈的概念、特点及存储结构2.栈的基本运算3.栈的应用4.队列的概念、特点及存储结构5.链队列、循环队列6.队列的应用及基本运算三、数组和广义表1.数组的顺序存储结构(二维及三维数组的元素地址计算)2.稀疏矩阵的压缩存储结构(三元组表、十字链表)四、树和二叉树1.二叉树的定义、性质及存储结构2.遍历二叉树和线索二叉树3.二叉树的应用五、图1.图的定义及存储结构(邻接矩阵表示和邻接表表示。
)2.图的遍历3.最小生成树4.拓扑排序六、查找1.静态表查找2.动态表查找(二叉排序树、平衡二叉树、B-树和B+树)3.哈希表的构造、哈希表的查找及分析、处理哈希冲突的方法七、内部排序1.插入排序、快速排序、选择排序、归并排序、基数排序等内部排序的特点与算法,各类排序方法的比较,时、空复杂度分析2.相关排序的应用考试题型:选择题(15%)、填空题(20%)、判断题(10%)、应用题(35%)、算法设计题(20%);其中算法设计题将着重考查学生使用C语言编程解决实际问题的能力,需要有一定的实际编程基础,而不是只会解书上的习题。
表示稀疏矩阵的十字链表
void invert(node *head)
{ node *p,*q,*r;
例
p=head;
q=p->next;
3
while(q!=NULL) /*没有后继时停止*/
.
{
1
r=q->next; q->next=p;
算
p=q;
法
q=r;
}
head->next=NULL;
head=p;
}
链表
例3.2
}
链表
例3.3
给出在双链表中第i个结点(i≥0)之后插入一个元素为x的 结点的函数。
解:在前面双链表一节中,已经给出了在一个结点之前 插入一个新结点的方法,在一个结点之后插入一个新结 点的思想与前面是一样的。
链表
void insert(dnode *head,int i,x)
{
dnode *s,*p;
link(node *head1,head2)
{
例
node *p,*q; p=head1;
3.
while(p->next!=head1)
2
p=p->next;
算
q=head2; while(q->next!=head2)
法
q=q->next;
p->next=head2;
q->next=head1;
对于每行、每列的循环链表都有一个空表 头结点,以利于元素的插入和删除运算。 这些空表头结点的行号、列号都标成零, 以便和其它结点相区别。
整个十字链表有一个总的空表头结点,在 一般结点标以行号、列号之处,此结点是 标出矩阵的行数m和列数n。
I第九讲(十字链表及基本操作)
(b)每行 列设一个表头结点(结构同元素结点), 每行/列设一个表头结点 结构同元素结点), 每行 列设一个表头结点( 为链构成循环链表, 以down/right为链构成循环链表,即第 列头结点的 为链构成循环链表 即第i列头结点的 down指向该列上第 个非 元素,第i 行头结点的 指向该列上第1个非 元素, 指向该列上第 个非0元素 right指向该行第 个非 元素.第i列/行上最后一个 指向该行第1个非 元素. 列 行上最后一个 指向该行第 个非0元素 结点的down/right指向该列 行的头结点.若某列 行 指向该列/行的头结点 若某列/行 结点的 指向该列 行的头结点. 中无非0元素 则令它的头结点down/right域指向自 元素, 中无非 元素,则令它的头结点 域指向自 己. (c)设一个总头结点(结构同元素结点),令总 设一个总头结点( ),令总 设一个总头结点 结构同元素结点), 头结点和各个列/行头结点用 字段 按列/行序构 头结点和各个列 行头结点用val字段,按列 行序构 行头结点用 字段, 成一个循环单链表. 成一个循环单链表.
row元素在稀疏矩阵中的行号col元素在稀疏矩阵中的列号val元素值down指向同列中下一个非0元素结点right指向同行中下一个非0元素结点rowcolvaldownrightb每行列设一个表头结点结构同元素结点以downri上第1个非0元素第i行头结点的right指向该行第1个非0元素
(d)可令总头结点的 可令总头结点的row,col与val 分别表示矩阵的 , 与 可令总头结点的 最大行号,列号与非0元素个数 元素个数, 最大行号,列号与非 元素个数,而down/right指向 指向 行的头结点. 第1列/行的头结点.该总头结点可作为整个十字链表 列 行的头结点 的代表. 的代表. (e)由于行与列的头结点分别使用 由于行与列的头结点分别使用right域与 域与down域 由于行与列的头结点分别使用 域与 域 (不同时使用 ,故第i列与第 行头结点可合用同一个 不同时使用),故第 列与第i 不同时使用 列与第 头结点(对所有可能的i),以节省存储空间. ),以节省存储空间 头结点(对所有可能的i),以节省存储空间. (f)有时,为了快速访问行 列头结点,设置一个一维 有时, 列头结点, 有时 为了快速访问行/列头结点 数组headNodes[] ,使headNodes[i]指向 行/列的 数组 指向i行 列的 指向 头结点.但这并不是必须的,因为各行/列的头结点 头结点.但这并不是必须的,因为各行 列的头结点 已形成了一个循环单链表, 已形成了一个循环单链表,故若已知十字链表总头 结点,即可搜索到任一头结点. 结点,即可搜索到任一头结点.
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
十字链表有向图
#include <iostream.h>
#define max 100
typedef struct arcnode{
int adjvex; int info; arcnode *nextacr;
}acrnode;
typedef struct{
char data;
acrnode *firstacr;
}vexnode;
typedef struct{
vexnode adj[max];
int n,e; //n=length,e边数
}graph;
int locatex(graph g,char x){
for(int i=0;i<g.n;i++)
if(x=g.adj[i].data)
return i;
return -1;
}
void create(graph &g,int m,int k){ //创建
g.n=m;
g.e=k;
int i,j;
for(i=0;i<m;i++){
cin>>g.adj[i].data;
g.adj[i].firstacr=NULL;
}
int h,t,w; //w为权值
char u,v;
acrnode *p;
for(i=0;i<k;i++){
cin>>u>>v>>w;
h=locatex(g,u);
t=locatex(g,v);
p=new acrnode;
p->adjvex=t;
p->info=w;
p->nextacr=g.adj[h].firstacr;
g.adj[h].firstacr=p;
}
}
int degree(graph g,char x){ //计算度数
int h=locatex(g,x);
int n=0;
acrnode *p=g.adj[h].firstacr;
while(p){
n++;
p=p->nextacr;
}
return n;
}
void addarc(graph &g,char u,char v,int w){ //增加一条边int h=locatex(g,u);
int t=locatex(g,v);
if(h==-1){
g.adj[g.n].data=u;
g.adj[g.n].firstacr=NULL;
h=g.n;
g.n++;
}
if(t==-1){
g.adj[g.n].data=v;
g.adj[g.n].firstacr=NULL;
t=g.n;
g.n++;
}
acrnode *p=new acrnode;
p->adjvex=t;
p->info=w;
p->nextacr=g.adj[h].firstacr;
g.adj[h].firstacr=p;
g.e++;
}
void main(void){
graph g;
create(g,5,6);
cout<<degree(g,'d')<<endl; //endl即换行
addarc(g,'f','h',20);
cout<<degree(g,'f')<<endl;
}
#include<iostream.h>
#define max 100
typedef struct arcnode{
int tailvex,headvex;
arcnode *tlink,*hlink;
}arcnode;
typedef struct{
char data;
arcnode *firstin,*firstout;
}vexnode;
typedef struct{
vexnode xlist[max];
int n,e;
}olgraph;
int locatex(olgraph g,char x){ //定位
for(int i=0;i<g.n;i++)
if(x==g.xlist[i].data)return i;
return -1;
}
void create(olgraph &g,int m,int k){ //m顶点n边g.n=m;g.e=k;
int i=0;
for(i=0;i<m;i++){
cin>>g.xlist[i].data;
g.xlist[i].firstin=g.xlist[i].firstout=NULL;
}
char u,v;
int t,h,w;
arcnode *p;
for(i=0;i<k;i++){
cin>>u>>v>>w;
t=locatex(g,u);
h=locatex(g,v);
p=new arcnode;
p->tailvex=t;
p->headvex=h;
p->info=w;
p->tlink=g.xlist[t].firstout;
g.xlist[t].firstout=p;
p->hlink=g.xlist[h].firstin;
g.xlist[h].firstin=p;
}
}
int outdegree(olgraph g,char x){ //出度
int h=locatex(g,x);
arcnode *p=g.xlist[h].firstout;
int n=0;
n++;
p=p->tlink;
}
return n;
}
int indegree(olgraph g ,char x){ //入度
int h=locatex(g,x);
arcnode *p=g.xlist[h].firstin;
int n=0;
while(p){
n++;
p=p->hlink;
}
return n;
}
void addarc(olgraph &g,char u,char v,int w){ //增加一条边int t=locatex(g,u);
int h=locatex(g,v);
if(t==-1){g.xlist[g.n].data=u;
g.xlist[g.n].firstout=g.xlist[g.n].firstin=NULL;
t=g.n; g.n++;
}
if(h==-1){g.xlist[g.n].data=v;
g.xlist[g.n].firstout=g.xlist[g.n].firstin=NULL;
h=g.n;
g.n++;
}
arcnode *p=new arcnode;
p->tailvex=t;
p->headvex=h;
p->info=w;
p->tlink=g.xlist[t].firstout;
g.xlist[t].firstout=p;
p->hlink=g.xlist[h].firstin;
g.xlist[h].firstin=p;
}
void main(void){
olgraph g;
create(g,5,6);
cout<<outdegree(g,'a')<<endl;
cout<<indegree(g,'e')<<endl;
addarc(g,'b','d',4);
cout<<indegree(g,'d');
}。