玩转C线性表和单向链表之Linux双向链表优化
前言:
这次介绍基本数据结构的线性表和链表,并用C语言进行编写;建议最开始学数据结构时,用C语言;像栈和队列都可以用这两种数据结构来实现。
一、线性表基本介绍
1 概念:
线性表也就是关系户中最简单的一种关系,一对一。
如:学生学号的集合就是一个线性表。
2 特征:
① 有且只有一个“首元素“。
② 有且只有一个“末元素”。
③ 除“末元素”外,其余元素均有唯一的后继元素。
④ 除“首元素”外,其余元素均有唯一的前驱元素。
3 存储划分:
① 如果把线性表用“顺序存储”,那么就是“顺序表”。
② 如果把线性表用“链式存储”,那么就是“链表”。
4 常用操作:
添加,删除,插入,查找,遍历,统计。
二、线性表实现
主要实现线性表的创建、销毁和插入等操作,将接口封装在.h文件中,如下:
#ifndef __MY_SEQLIST_H__
#define __MY_SEQLIST_H__ typedef void SeqList;
typedef void SeqListNode; SeqList* SeqList_Create(int capacity); //创建线性表 void SeqList_Destroy(SeqList* list); //销毁 void SeqList_Clear(SeqList* list); //清空 int SeqList_Length(SeqList* list); //求线性表的长度 int SeqList_Capacity(SeqList* list); //求线性表的容量 int SeqList_Insert(SeqList* list, SeqListNode* node, int pos); //向线性表中插入元素 SeqListNode* SeqList_Get(SeqList* list, int pos); //获取指定位置元素 SeqListNode* SeqList_Delete(SeqList* list, int pos); //删除指定位置元素 #endif //__MY_SEQLIST_H__
注意:定义头文件时,要包含“#ifndef”,防止头文件重复包含!
1、线性表创建
主要就是对节点分配内存,代码如下:
//在结构体中套1级指针
//
typedef struct _tag_SeqList
{
int length;
int capacity;
unsigned int *node; //int* node[]
}TSeqList; SeqList* SeqList_Create(int capacity)
{
int ret = ;
TSeqList *tmp = NULL; tmp = (TSeqList *)malloc(sizeof(TSeqList));
if (tmp == NULL)
{
ret = -;
printf("func SeqList_Create() err:%d \n", ret);
return NULL;
}
memset(tmp, , sizeof(TSeqList)); //根据capacity 的大小分配节点的空间
tmp->node = (unsigned int *)malloc(sizeof(unsigned int *) * capacity);
if (tmp->node == NULL)
{
ret = -;
printf("func SeqList_Create() err: malloc err %d \n", ret);
return NULL;
}
tmp->capacity = capacity;
tmp->length = ;
return tmp;
} void SeqList_Destroy(SeqList* list)
{
TSeqList *tlist = NULL;
if (list == NULL)
{
return ;
}
tlist = (TSeqList *)list;
if (tlist->node != NULL)
{
free(tlist->node);
} free(tlist); return ;
}
2、线性表插入
插入在业界有默认的规则吧,下面将要讲到的链表也是用这个规则。用图来讲解一下吧,如下:
讲解:例如,已经有线性表34、33、32、31,在1位置想插入35,想把从1开始的先后移,再插入,插入后的线性表如右图所示。
线性表插入代码如下:
int SeqList_Insert(SeqList* list, SeqListNode* node, int pos)
{
int i =, ret = ;
TSeqList *tlist = NULL; if (list == NULL || node==NULL || pos<)
{
ret = -;
printf("fun SeqList_Insert() err:%d \n", ret);
return ret;
}
tlist = (TSeqList*)list; //判断是不是满了
if (tlist->length >= tlist->capacity)
{
ret = -;
printf("fun SeqList_Insert() (tlist->length >= tlist->capacity) err:%d \n", ret);
return ret;
} //容错修正 6个长度 容量20;用户pos10位置插入..
if (pos>=tlist->length)
{
pos = tlist->length; //
} //1 元素后移
for(i=tlist->length; i>pos; i--)
{
tlist->node[i] = tlist->node[i-];
//a[7] = a[6]
}
// i = 3
// 2插入元素
tlist->node[i] = (unsigned int )node;
tlist->length ++;
return ;
}
3、获取指定位置元素
根据pos位置获取元素,代码如下:
SeqListNode* SeqList_Get(SeqList* list, int pos)
{
int i =;
SeqListNode *ret = ;
TSeqList *tlist = NULL; if (list == NULL || pos<)
{
printf("fun SeqList_Get() err:%d \n", ret);
return NULL;
}
tlist = (TSeqList*)list; ret = (void *)tlist->node[pos];
return ret;
}
4、删除指定位置元素
将指定位置的元素进行删除,代码如下:
SeqListNode* SeqList_Delete(SeqList* list, int pos)
{
int i = ;
SeqListNode *ret = ;
TSeqList *tlist = NULL; if (list == NULL || pos<) //检查
{
printf("fun SeqList_Delete() err:%d \n", ret);
return NULL;
}
tlist = (TSeqList*)list; ret = (SeqListNode *)tlist->node[pos]; //缓存pos的位置 for (i=pos+; i<tlist->length; i++) //pos位置后面的元素前移
{
tlist->node[i-] = tlist->node[i];
}
tlist->length --;
return ret;
}
5、总体代码
整个seqlist.c代码如下,方便使用与调试:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "seqlist.h" //在结构体中套1级指针
//
typedef struct _tag_SeqList
{
int length;
int capacity;
unsigned int *node; //int* node[]
}TSeqList; SeqList* SeqList_Create(int capacity)
{
int ret = ;
TSeqList *tmp = NULL; tmp = (TSeqList *)malloc(sizeof(TSeqList));
if (tmp == NULL)
{
ret = -;
printf("func SeqList_Create() err:%d \n", ret);
return NULL;
}
memset(tmp, , sizeof(TSeqList)); //根据capacity 的大小分配节点的空间
tmp->node = (unsigned int *)malloc(sizeof(unsigned int *) * capacity);
if (tmp->node == NULL)
{
ret = -;
printf("func SeqList_Create() err: malloc err %d \n", ret);
return NULL;
}
tmp->capacity = capacity;
tmp->length = ;
return tmp;
} void SeqList_Destroy(SeqList* list)
{
TSeqList *tlist = NULL;
if (list == NULL)
{
return ;
}
tlist = (TSeqList *)list;
if (tlist->node != NULL)
{
free(tlist->node);
} free(tlist); return ;
} //清空链表 //回到初始化状态
void SeqList_Clear(SeqList* list)
{
TSeqList *tlist = NULL;
if (list == NULL)
{
return ;
}
tlist = (TSeqList *)list;
tlist->length = ;
return ;
} int SeqList_Length(SeqList* list)
{
TSeqList *tlist = NULL;
if (list == NULL)
{
return -;
}
tlist = (TSeqList *)list;
return tlist->length;
} int SeqList_Capacity(SeqList* list)
{ TSeqList *tlist = NULL;
if (list == NULL)
{
return -;
}
tlist = (TSeqList *)list;
return tlist->capacity;
} int SeqList_Insert(SeqList* list, SeqListNode* node, int pos)
{
int i =, ret = ;
TSeqList *tlist = NULL; if (list == NULL || node==NULL || pos<)
{
ret = -;
printf("fun SeqList_Insert() err:%d \n", ret);
return ret;
}
tlist = (TSeqList*)list; //判断是不是满了
if (tlist->length >= tlist->capacity)
{
ret = -;
printf("fun SeqList_Insert() (tlist->length >= tlist->capacity) err:%d \n", ret);
return ret;
} //容错修正 6个长度 容量20;用户pos10位置插入..
if (pos>=tlist->length)
{
pos = tlist->length; //
} //1 元素后移
for(i=tlist->length; i>pos; i--)
{
tlist->node[i] = tlist->node[i-];
//a[7] = a[6]
}
// i = 3
// 2插入元素
tlist->node[i] = (unsigned int )node;
tlist->length ++;
return ;
} SeqListNode* SeqList_Get(SeqList* list, int pos)
{
int i =;
SeqListNode *ret = ;
TSeqList *tlist = NULL; if (list == NULL || pos<)
{
printf("fun SeqList_Get() err:%d \n", ret);
return NULL;
}
tlist = (TSeqList*)list; ret = (void *)tlist->node[pos];
return ret;
} SeqListNode* SeqList_Delete(SeqList* list, int pos)
{
int i = ;
SeqListNode *ret = ;
TSeqList *tlist = NULL; if (list == NULL || pos<) //检查
{
printf("fun SeqList_Delete() err:%d \n", ret);
return NULL;
}
tlist = (TSeqList*)list; ret = (SeqListNode *)tlist->node[pos]; //缓存pos的位置 for (i=pos+; i<tlist->length; i++) //pos位置后面的元素前移
{
tlist->node[i-] = tlist->node[i];
}
tlist->length --;
return ret;
}
6、调试
写一个main函数,进行上面的接口调用与调试,代码如下:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "seqlist.h"
typedef struct _Teacher
{
int age;
char name[];
}Teacher; void main()
{
int ret = , i = ;
SeqList* list = NULL; Teacher t1, t2, t3, t4,t5;
t1.age = ;
t2.age = ;
t3.age = ;
t4.age = ;
t5.age = ; list = SeqList_Create();
if (list == NULL)
{
printf("func SeqList_Create() ret :%d \n", ret);
return ;
} ret = SeqList_Insert(list, (SeqListNode*) &t1, ); //头插法
ret = SeqList_Insert(list, (SeqListNode*) &t2, ); //头插法
ret = SeqList_Insert(list, (SeqListNode*) &t3, ); //头插法
ret = SeqList_Insert(list, (SeqListNode*) &t4, ); //头插法
ret = SeqList_Insert(list, (SeqListNode*) &t5, ); //头插法 //遍历
for (i=; i<SeqList_Length(list); i++)
{
Teacher* tmp = (Teacher *) SeqList_Get(list, i);
if (tmp == NULL)
{
return ;
}
printf("tmp->age:%d ", tmp->age);
} //删除链表中的节点
while( SeqList_Length(list) > )
{
SeqList_Delete(list, );
} system("pause"); return ;
}
三、链表
1、介绍
链表的大体有三种实现方式,用图进行讲解吧,如下图:
说明:最上面就是最传统链表,每个节点存一个next指针,保存下一个节点的地址
中间是linux内核实现的链表,一般是双向链表,有一个缺点要记录偏移量
最后是改进之后的链表,不需要记录偏移量,这是前人的智慧,我将采用最后一种进行实现。
2、定义头文件
头文件主要包含结构体定义,和接口声明,主要实现链表初始化、插入、遍历等操作,头文件如下:
#ifndef LINKLIST_H
#define LINKLIST_H #include<stdlib.h>
#include<stdio.h> //链表结点
typedef struct LINKNODE{
void* data; //指向任何类型的数据
struct LINKNODE* next;
}LinkNode; //链表结构体
typedef struct LINKLIST{
LinkNode* head;
int size;
}LinkList; //定义函数指针
typedef void(*PRINTLINKNODE)(void*); //初始化链表
LinkList* Init_LinkList();
//指定位置插入
void Insert_LinkList(LinkList* list,int pos,void* data);
//删除指定位置的值
void RemoveByPos_LinkList(LinkList* list, int pos);
//获得链表的长度
int Size_LinkList(LinkList* list);
//查找
int Find_LinkList(LinkList* list,void* data);
//返回第一个结点
void* Front_LinkList(LinkList* list);
//打印链表结点
void Print_LinkList(LinkList* list, PRINTLINKNODE print);
//释放链表内存
void FreeSpace_LinkList(LinkList* list); #endif
3、插入节点
初始化链表跟线性表类似,就不在过多说明了,主要讲解插入和删除节点,对插入节点进行讲解,如下图:
说明:需要两个指针current、node,假如在3号位置进行插入,要先处理node->next,node指向3号位置,就把3号位置指针付给它,node->next=current->next;
2号位置指向node,把node指针赋值给它,current->next=node;
注意:图片左下角的红字,是理解链表插入、删除等的关键!
代码如下:
//指定位置插入
void Insert_LinkList(LinkList* list, int pos, void* data){ if (list == NULL){
return;
}
if (data == NULL){
return;
} //友好的处理,pos越界
if (pos < || pos > list->size) {
pos = list->size;
} //创建新的结点
LinkNode* newnode = (LinkNode*)malloc(sizeof(LinkNode));
newnode->data = data;
newnode->next = NULL; //找结点
//辅助指针变量
LinkNode* pCurrent = list->head;
for (int i = ; i < pos;i++){
pCurrent = pCurrent->next;
} //新结点入链表
newnode->next = pCurrent->next;
pCurrent->next = newnode; list->size++;
}
4、删除节点
说明:
删除3号位置,先保存被删除节点的位置,再将2直接指向4;
5、整体代码
整个的代码,方便大家使用和调试,代码如下:
#include"LinkList.h" //初始化链表
LinkList* Init_LinkList(){ LinkList* list = (LinkList*)malloc(sizeof(LinkList));
list->size = ; //头结点 是不保存数据信息
list->head = (LinkNode*)malloc(sizeof(LinkNode));
list->head->data = NULL;
list->head->next = NULL; return list;
}
//指定位置插入
void Insert_LinkList(LinkList* list, int pos, void* data){ if (list == NULL){
return;
}
if (data == NULL){
return;
} //友好的处理,pos越界
if (pos < || pos > list->size) {
pos = list->size;
} //创建新的结点
LinkNode* newnode = (LinkNode*)malloc(sizeof(LinkNode));
newnode->data = data;
newnode->next = NULL; //找结点
//辅助指针变量
LinkNode* pCurrent = list->head;
for (int i = ; i < pos;i++){
pCurrent = pCurrent->next;
} //新结点入链表
newnode->next = pCurrent->next;
pCurrent->next = newnode; list->size++; }
//删除指定位置的值
void RemoveByPos_LinkList(LinkList* list, int pos){
if (list == NULL){
return;
} if (pos < || pos >= list->size){
return;
} //查找删除结点的前一个结点
LinkNode* pCurrent = list->head;
for (int i = ; i < pos;i ++){
pCurrent = pCurrent->next;
} //缓存删除的结点
LinkNode* pDel = pCurrent->next;
pCurrent->next = pDel->next;
//释放删除结点的内存
free(pDel); list->size--;
}
//获得链表的长度
int Size_LinkList(LinkList* list){
return list->size;
}
//查找
int Find_LinkList(LinkList* list, void* data){
if (list == NULL){
return -;
} if (data == NULL){
return -;
} //遍历查找
LinkNode* pCurrent = list->head->next;
int i = ;
while (pCurrent != NULL){
if (pCurrent->data == data){
break;
}
i++;
pCurrent = pCurrent->next;
} return i;
}
//返回第一个结点
void* Front_LinkList(LinkList* list){
return list->head->next->data;
}
//打印链表结点
void Print_LinkList(LinkList* list, PRINTLINKNODE print){
if (list == NULL){
return;
}
//辅助指针变量
LinkNode* pCurrent = list->head->next;
while (pCurrent != NULL){
print(pCurrent->data);
pCurrent = pCurrent->next;
} }
//释放链表内存
void FreeSpace_LinkList(LinkList* list){ if (list == NULL){
return;
} //辅助指针变量
LinkNode* pCurrent = list->head;
while (pCurrent != NULL){
//缓存下一个结点
LinkNode* pNext = pCurrent->next;
free(pCurrent);
pCurrent = pNext;
} //释放链表内存
list->size = ;
free(list); }
6、调试代码
写一个main函数进行调试,如下:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "LinkList.h" //自定义数据类型
typedef struct PERSON{
char name[];
int age;
int score;
}Person; //打印函数
void MyPrint(void* data){
Person* p = (Person*)data;
printf("Name:%s Age:%d Score:%d\n",p->name,p->age,p->score);
} int main(void){ //创建链表
LinkList* list = Init_LinkList(); //创建数据
Person p1 = { "aaa", , };
Person p2 = { "bbb", , };
Person p3 = { "ccc", , };
Person p4 = { "ddd", , };
Person p5 = { "eee", , }; //数据插入链表
Insert_LinkList(list, , &p1);
Insert_LinkList(list, , &p2);
Insert_LinkList(list, , &p3);
Insert_LinkList(list, , &p4);
Insert_LinkList(list, , &p5); //打印
Print_LinkList(list, MyPrint); //删除3
RemoveByPos_LinkList(list, ); //打印
printf("---------------\n");
Print_LinkList(list, MyPrint); //返回第一个结点
printf("-----查找结果------------\n");
Person* ret = (Person*)Front_LinkList(list);
printf("Name:%s Age:%d Score:%d\n", ret->name, ret->age, ret->score); //销毁链表
FreeSpace_LinkList(list); system("pause");
return ;
}
运行结果如下,供参考:
四、补充C++实现链表
1、头文件
头文件LinkedList.h,代码如下:
#include <iostream> template<class T>
class Node { //节点类
public:
T e; //数据域
Node *next; //指针域 Node(T e, Node *next) : e(e), next(next) { //构造函数的列表初始化
} Node(T e) : e(e), next(nullptr) {
} Node() : next(nullptr) { //无参构造函数
}
}; template<class T>
class LinkedList {
private:
Node<T> *head; //头结点
int size;
public:
class Range {
}; class Empty {
}; LinkedList() { //构造函数
head = new Node<T>();
size = ;
} int getSize() { //获取大小
return size;
} bool isEmpty() { //判断是否为空
return size == ;
} void add(int index, T e) { //指定位置插入元素
if (index < || index > size) {
throw Range();
}
Node<T> *prev = head;
for (int i = ; i < index; ++i) {
prev = prev->next;
}
prev->next = new Node<T>(e, prev->next);
size++;
} void addFirst(T e) { //插入元素 头插法
add(, e);
} void addLast(T e) { //插入元素 尾插法
add(size, e);
} T get(int index) { //获取元素
if (size == ) {
throw Empty();
}
if (index < || index >= size) {
throw Range();
}
Node<T> *cur = head->next;
for (int i = ; i < index; ++i) {
cur = cur->next;
}
return cur->e;
} T getFirst() {
return get();
} T getLast() {
return get(size - );
} void set(int index, T e) {
if (size == ) {
throw Empty();
}
if (index < || index >= size) {
throw Range();
}
Node<T> *cur = head->next;
for (int i = ; i < index; ++i) {
cur = cur->next;
}
cur->e = e;
} void setFirst(T e) {
set(, e);
} void setLast(T e) {
set(size - , e);
} T remove(int index) { //删除指定位置元素
if (index < || index >= size) {
throw Range();
}
if (size == ) {
throw Empty();
}
Node<T> *prev = head;
for (int i = ; i < index; ++i) {
prev = prev->next;
}
Node<T> *retNode = prev->next;
prev->next = retNode->next;
retNode->next = nullptr;
size--;
return retNode->e;
} T removeFirst() {
return remove();
} T removeLast() {
return remove(size - );
} void removeElement(T e) {
Node<T> *prev = head;
while (prev->next != nullptr) {
if (prev->next->e == e) {
break;
}
prev = prev->next;
} if (prev->next != nullptr) {
Node<T> *delNode = prev->next;
prev->next = delNode->next;
delNode->next = nullptr;
size--;
}
} bool contains(T e) { //是否包含
Node<T> *cur = head;
for (int i = ; i < size; ++i) {
cur = cur->next;
if (cur->e == e) {
return true;
}
}
return false;
} void print() { //打印输出
Node<T> *prev = head;
std::cout << "LinkedList: size = " << size << std::endl;
std::cout << "[";
for (int i = ; i < size; ++i) {
prev = prev->next;
std::cout << prev->e;
if (i < size - ) {
std::cout << ", ";
}
}
std::cout << "]" << std::endl;
}
};
2、main函数
main.cpp如下:
#include <iostream>
#include "LinkedList.h" int main() {
LinkedList<int> *linkedList = new LinkedList<int>();
for (int i = ; i < ; ++i) {
linkedList->addFirst(i); //头插法
}
linkedList->add(, ); //指定位置插入元素
linkedList->print(); //打印输出
linkedList->remove(); //删除指定位置元素
linkedList->print();
linkedList->removeFirst();
linkedList->print();
linkedList->removeLast();
linkedList->print();
return ;
}
3、测试
运行结果如下:
总结
虽然线性表和单向链表是数据结构的基础,但完全掌握之后,再学习栈、队列等数据结构将会得心应手;
喜欢的希望帮忙点赞,不懂的欢迎随时留言!
玩转C线性表和单向链表之Linux双向链表优化的更多相关文章
- c/c++ 线性表之单向链表
c/c++ 线性表之单向链表 线性表之单向链表 不是存放在连续的内存空间,链表中的每个节点的next都指向下一个节点,最后一个节点的下一个节点是NULL. 真实的第一个节点是头节点,头节点不存放数据, ...
- 数据结构C语言实现系列——线性表(单向链表)
#include <stdio.h> #include <stdlib.h> #define NN 12 #define MM 20 typedef int elemType ...
- c/c++ 线性表之单向循环链表
c/c++ 线性表之单向循环链表 线性表之单向循环链表 不是存放在连续的内存空间,链表中的每个节点的next都指向下一个节点,最后一个节点的下一个节点不是NULL,而是头节点.因为头尾相连,所以叫单向 ...
- [数据结构-线性表1.2] 链表与 LinkedList<T>(.NET 源码学习)
[数据结构-线性表1.2] 链表与 LinkedList<T> [注:本篇文章源码内容较少,分析度较浅,请酌情选择阅读] 关键词:链表(数据结构) C#中的链表(源码) 可空类 ...
- 线性表之单链表C++实现
线性表之单链表 一.头文件:LinkedList.h //单链表是用一组任意的存储单元存放线性表的元素,这组单元可以是连续的也可以是不连续的,甚至可以是零散分布在内存中的任意位置. //单链表头文件 ...
- [数据结构 - 第3章] 线性表之单链表(C++实现)
一.类定义 单链表类的定义如下: #ifndef SIGNALLIST_H #define SIGNALLIST_H typedef int ElemType; /* "ElemType类型 ...
- K:线性表的实现—链表
单链表的概念: 采用链式存储方式存储的线性表称之为链表,链表中每个节点包含存放数据元素的值的数据域和存放指向逻辑上相邻节点的指针域.若一个节点中只包含一个指针域,则称此链表为单链表. 单链表的特点: ...
- 数据结构 1 线性表详解 链表、 栈 、 队列 结合JAVA 详解
前言 其实在学习数据结构之前,我也是从来都没了解过这门课,但是随着工作的慢慢深入,之前学习的东西实在是不够用,并且太皮毛了.太浅,只是懂得一些浅层的,我知道这个东西怎么用,但是要优化.或者是解析,就不 ...
- 续上文----线性表之单链表(C实现)
本文绪上文线性表之顺序表(C实现) 本文将继续使用单链表实现线性表的另外一种存储结构.这种使用链表实现的存储结构在内存中是不连续的. C实现代码如下: #include<stdio.h> ...
随机推荐
- 勾勾街:用最小的成本封装一个苹果IOS APP! 封装技术再度升级~
勾勾街自上线以来,“遭到”大量群众的喜爱... 只能用遭到这个词儿,因为大家好像都被憋了很久了,哈哈哈! 我们的技术是先进的,也是首创的,但最近发现了另一个网站,把我们的技术抄走了.... 本来这个事 ...
- UWB DWM1000 跟随小车原理---一张图演示
更多内容参考论坛:bphero.com.cn
- Numpy 基础运算2
# -*- encoding:utf-8 -*- # Copyright (c) 2015 Shiye Inc. # All rights reserved. # # Author: ldq < ...
- springboot排除exclude
@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
- 通过命令行操作MYSQL的方法 以及导入大的SQL备份文件
运行 输入CMD 进入 命令行窗口 输入Mysql.exe的路径 如:c:/wamp/bin/mysql.exe 回车 这时出现 welcome to the mysql ...的提示 进入成 ...
- 等高布局display:table
display:table用法: 父元素:display:table; 子元素:display:table-cell; 注:使用display:table-cell元素部分出现空白缝隙的问题:设置 . ...
- H5测试点总结-UI测试、功能测试、兼容性测试、体验相关(弱网、资源、手机操作等)、安全性测试、性能测试
一.概述 1.1 什么是H5 H5 即 HTML5,是最新的 Web 端开发语言版本,现如今,大多数手机 APP 页面会用 H5 实现,包括 PC Web 站点也会用它开发实现.所以 Web 的通用测 ...
- Http_4个新的http状态码:428、429、431、511
1.428 Precondition Required (要求先决条件) 先决条件是客户端发送 HTTP 请求时,必须要满足的一些预设条件.一个好的例子就是 If-None-Match 头,经常用在 ...
- 2019_BUAAOO_第一单元总结
前言 OO第一单元共有三次作业,分别为多项式求导.带有三角函数与幂函数的表达式求导.带有嵌套表达式因子的表达式求导.虽然这三次作业都离不开求导,可是每次作业的复杂度都是大大递增的.对于习惯于面向过程编 ...
- ArcMap AddIn之下载ArcGIS Server地图服务中的数据
涉及到开发知识点1.ArcGIS Server地图服务 2.C# web请求获取数据 3.AddIN开发技术 工具界面: 具体涉及到的代码之后有空贴出来.先上工具 AddIn插件下载地址:点击这里下载 ...