网站建设低价网站到底便宜在哪,越烽建设集团有限公司网站,建设网站基础,番禺响应式网站建设绪论 机遇对于有准备的头脑有特别的亲和力。本章将讲写到链表其中主要将写到单链表和带头双向循环链表的如何实现。 话不多说安全带系好#xff0c;发车啦#xff08;建议电脑观看#xff09;。 附#xff1a;红色#xff0c;部分为重点部分#xff1b;蓝颜色为需要记忆的… 绪论 机遇对于有准备的头脑有特别的亲和力。本章将讲写到链表其中主要将写到单链表和带头双向循环链表的如何实现。 话不多说安全带系好发车啦建议电脑观看。 附红色部分为重点部分蓝颜色为需要记忆的部分不是死记硬背哈多敲黑色加粗或者其余颜色为次重点黑色为描述需要 目录
链表
1.单链表
1.1.单链表的结构
1.2放入数据到单链表中
1.3 删除单链表中的数据
1.4 摧毁单链表
1.5单链表的打印
2.带头双向循环列表
2.1带头双向链表的结构
2.2双向链表的初始化
2.3双向链表中放入数据
2.4双向链表中的删除数据
2.5双向链表的摧毁
2.6打印双向链表中的各个数据
3.如何快速的实现一个链表 链表
知识点 链表是一个在逻辑上连续的线性结构但在物理结构上他的地址并不是连续的是通过指针的形式链接而成的一个非顺序的存储结构。 细节
链表的属性 单向/双向、循环/不循环、带头/不带头 对此就能有多种排列组合但我们主要学的是单链表单向、不带头、不循环、带头双向循环链表因为这两个链表最具代表性且常用当我们学会这两种链表后其他的链表基本也不在话下 对于上面的属性其实也很好理解下面通过一张图片具体展示 其中节点表示的就是每个数据的每个小空间图中的矩形 1.单链表 单链表是我们在链表中最简单的一种链表形式因为过于简单所以其一般并不会用于存储数据但却经常出现于习题以及笔试面试题中并且还会作为一些数据结构的子结构如图的领接表、哈希桶中。 单链表的基本框架 1. 单链表的结构 1.一个数剧date存储当前位置的数据 2.一个指针next指向下一个数据 2. 所要实现的功能 1.将数据放入结构中 2.查找单链表中的某个的数据 3.将数据从结构中删除删除节点前提是要先找到该节点所在的位置 4.将数据展现打印出来 5.摧毁单链表 1.1.单链表的结构
单链表的是由数据、指针组成
typedef struct SListNode
{SLDateType data;//SLDateType typedef定义类型和顺序表一样都是为了更加方便去改变结构中的存的类型struct SListNode* next;//定义一个结构体类型的指针因为到时候next指向一个结构体类型
}SListNode;//用typedef将struct SListNode改变成SListNode这样更方便于我们后面使用可以不用加上struct直接用代替的就好//typedef int SLDateType; int重命名为SLDateType 1.2放入数据到单链表中
在插入数据之前需要先开辟好空间也就是创建节点
SListNode* BuySListNode(SLDateType x) {//接收传进来的数据SListNode* newnode (SListNode*)malloc(sizeof(SListNode));//用malloc开辟一个结构体大小的空间给新节点if (newnode NULL)//熟系的判断是否申请成功{perror(malloc failed);return NULL;}newnode-data x;//在申请的结构体空间中放入数据newnode-next NULL;//将其下一个位置暂时指向NULLreturn newnode;//返回这个节点返回类型是个指针类型也就是newnode的地址
}
申请好空间后就可以进行插入数据并且链接了 尾插从尾部插入分析尾部的特征是其下一个指向的是NULL对此就能找到最后一个数据的位置将其指向的NULL改成新节点的位置即可。 void SListPushBack(SListNode** pphead, SLDateType x) {//注意此处用二级指针是因为可能要修改结构体变量或理解成传进来的是一级指针类型为了修改他就需要用二级指针assert(pphead);//判空注意此处的判空是判的pphead 而不是 STL*pphead SListNode* newnode BuySListNode(x);//先创建一个新节点,调用创建节点的函数SListNode* tail *pphead;//一个指针指向链表开始可能为NULLif (*pphead NULL)//此处就是一个类似初始化的步骤{*pphead newnode;//此处修改了了结构体变量即修改了STL的指向指向新创建的链表的开始}else {//当不是最开始时就正常的进行尾插 while (tail-next) {//找尾部的NULLtail tail-next;//没找到就改变tail 让其变成next 继续往后找}tail-next newnode;//找到后把最后一个位置的数据的next 变成 新节点即可}
} 动图展示具体步骤头插比较简单直接看注释就能理解 //头插就会简单很多
void SListPushFront(SListNode** pphead, SLDateType x){//同样用到二级指针因为需要改变链表结构体变量assert(pphead);SListNode* newnode BuySListNode(x);//创建节点newnode-next *pphead;//将新开辟的空间的地址指向链表原本第一个元素的 地址*pphead newnode;//改变链表的起始地址
} 从指定位置插入数据 单独拎出来是因为其比较特殊它可以分为在pos位置前插入数据和在pos位置后插入数据两种并且我们在使用前需要先找到指定的位置后才能进行数据的插入所以还需要先写一个查找数据的函数接口。查找单链表中的某个数据思路类似于尾插 SListNode* SListFind(SListNode* phead, SLDateType x) {//指针接收结构体SListNode* find phead;while (find)//一个循环来找想要的数据{if (find-data x)//当找到时{return find;//返回此处的地址}find find-next;//不断往后找和找尾方法一样}printf(找不到\n);return NULL;//若找不到返回NULL
} 有了之后我们就可以利用这个查找函数还进行对该数据的前/后插入数据了 先向pos位置前插入一般不考虑这种因为比较麻烦且效率低多在后面插入数据 void SListInsertFront(SListNode** pphead,SListNode* pos, SLDateType x) {//当是在pos位置前面插入时就要考虑头插了所以可能会改变链表的开始就需要用到二级指针assert(pphead);assert(pos); if (pos *pphead)//如果pos位置在第一个那就等于在第一个位置前面插入数据也就是头插{SListPushFront(pphead, x);//此处用pphead因为pphead已经是一个二级指针了}else{SListNode* tail *pphead;while (tail-next ! pos)//找到pos位置的前一个位置{tail tail-next;}SListNode* newnode BuySListNode(x);//申请一个节点newnode-next tail-next;//先把newnode的指针改变这样避免当tail改变后找不到tail-next的情况tail-next newnode;//再将tail-next 指向改变成 newnode}
} 先pos位置之后插入数据 void SListInsertAfter(SListNode* pos, SLDateType x) {//此处把链表的地址传给了posassert(pos);SListNode* newnode BuySListNode(x);//创建新节点newnode-next pos-next;//先改变newnode的节点pos-next newnode;//再把pos-next改成newnode
} 附当不给头怎么才能在pos位置前面的插入数据有一种思路现在其pos位置后面插入一个数据然后再将pos位置的值和后面插入的值进行交换就相当于在pos位置前插入数据了。 1.3 删除单链表中的数据 尾删找到倒数第二个数据的位置后再把最后一个位置的空间进行释放即可然后把倒数第二个位置的next指向NULL。 void SListPopBack(SListNode** pphead) {//可能会修改外部数据所以用二级指针assert(pphead);//判空assert(*pphead);//判空防止第一个位置都没有if ((*pphead)-next NULL)//查看第一个数据位置是不是最后一个数据如果是的话{free(*pphead);//直接释放第一个位置的数据即可*pphead NULL;//把没用的指针置为NULL}else{SListNode* tail *pphead;//用tail代替*pphead使*pphead不被改变while (tail-next-next) {//往后看两位当为空时就表示到了倒数第二的位置tail tail-next;//一步一步走}free(tail-next);//找到后tail表示的是倒数第二而tail-next就是尾free释放尾即可tail-next NULL;//tail-next改变成NULL因为此时tail变成了最后一个数据}
} 头删分析首先我们肯定是需要一个二级指针接收来改变链表的开始其次就是要用一个临时指针指向头的位置先把头改成下一个位置然后把临时变量指向的原本的头的空间释放。 void SListPopFront(SListNode** pphead) {assert(pphead);//防止pphead为空assert(*pphead);//查看是否有第一个数据SListNode* frist *pphead;//记录第一个数据的位置*pphead frist-next;//改变链表的头改成下一个位置可能为空当只有一个数据的时候free(frist);//(释放第一个数据的位置)frist NULL;//没有的指针置为空
}在pos位置/pos位置后删除数据 在前面已经提过在pos位置前面插入基本不会用到所以此处就不再写了 在pos位置处删除需要先找到pos位置前面的数据然后后才能改变链接关系void SListErase(SListNode** pphead,SListNode* pos) {assert(pos);//不用再对*pphead进行检查了因为pos已经间接的检查了*pphead 检查的是是否链表中是否有数据假如没有的话pos也会报错assert(pphead);//判空SListNode* tail *pphead;if (*pphead pos)//若是第一个元素{SListPopFront(pphead);//那就直接头删}else{while (tail-next ! pos)//找到pos位置的前一个位置{tail tail-next;}tail-next pos-next;//将前面位置的next改变成pos位置的next这样就把pos位置给断开了free(pos);//把pos位置处的空间给释放}
} 把pos位置后面的数据删除方法很简单同样就是改变链接关系即可即吧pos-next pos-next-next即先找到pos位置后面的数据然后把pos的next改成后面数据的next即可思想和上面的是一样的 void SListEraseAfter(SListNode* pos) {assert(pos);if (pos-next NULL)//注意查看pos位置后面是否还有数据{return;//若没有则直接返回了}else {SListNode* del pos-next;//记录pos后面的位置pos-next pos-next-next;//改变链接关系让pos的后面位置指向pos位置后的后面位置free(del);//释放deldel NULL;}
} 若没给头怎么删除pos位置处的数据呢可以先存一份pos位置后面的数据再将后面的数据给赋给pos位置再把pos位置后面的数据给删除即可。 1.4 摧毁单链表 从前往后的依次free单链表不能从后往前是因为找不到是前面的数据的并且注意还需要一个指针来在后面才能保证释放前面数据后能找到后面的数据。 void SListDestroy(SListNode* plist) {assert(plist);SListNode* prev, * tail;//双指针prev plist;//指向头tail plist-next;//指向第二个数据的位置while (prev)//当prveNULL就不用进循环了也表示释放完了{ free(prev);//释放prev出的空间prev tail;//将prve指向tailif(tail ! NULL)//判断tail是不是NULLtail tail-next;//若是NULL就不能再往后了}plist NULL;//将没用的指针赋成空指针
} 1.5单链表的打印 直接遍历整个数组然后找到其数据进行打印 void SListPrint(SListNode* phead)
{SListNode* tail phead;//用一个指针来指向开始while (tail ! NULL)//只要tail不到NULL都要进群{printf(%d-, tail-data);//进来打印tail的datetail tail-next;//往后走}printf(NULL\n);//打印一下最后的NULL
} 附为什么要用二级指针
因为如果不用二级指针的话就无法改变传进来的参数只是传调用无法改变参数所以只有用传址调用能改变形参而传递进来的是一个一级指针类型所以我们就需要二级指针类型来接收他的地址接收指针类型的指针三步法。 2.带头双向循环列表
知识点 本质还是一个链表所以还是一样的通过指针的方法链接但是需要我们去改变一下结构增加了一个prev指针指向前面的数据。结构最复杂一般用在单独存储数据。实际中使用的链表数据结构都是带头双向循环链表。另外这个结构虽然结构复杂但是使用代码实现以后会发现结构会带来很多优势实现反而简单了。 细节
带头双向循环链表的基本框架 带头双向循环链表的结构 一个变量存数据一个指针指向前面的数据一个指针指向后面的数据带头双向循环链表所要实现的功能 初始化结构将数据放进结构中将数据从结构中删除在指定位置处插入/删除数据 2.1带头双向链表的结构
它的结构是由存数据的变量、两个分别指向前后的指针组成的
typedef int LTDataType;typedef struct ListNode
{LTDataType data;//数据struct ListNode* next;//指向后面的数据struct ListNode* prev;//指向前面的数据//struct ListNode结构体类型这里要加上struct因为类型重命名是在后面的
}ListNode;//typedef类型重命名
2.2双向链表的初始化
在那之前还需要去写一个申请空间的接口
ListNode* BuyMemory(LTDataType x)//申请空间的函数
{ListNode* node (ListNode*)malloc(sizeof(ListNode));//malloc申请一个大小为一个结构体一个节点的空间if (node NULL)//若申请失败{perror(malloc::BuyMemory);//报错//return NULL;exit(-1);//直接退出程序}node-data x;//将申请中的空间数据置为给定的xnode-next NULL;//将next先置为NULLnode-prev NULL;//将prev先置为NULLreturn node;//返回借号的空间
}
因为是带头的链表所以需要去先申请一个空间给头
ListNode* ListCreate()//给头申请空间并且返回头指针的地址
{ListNode* head BuyMemory(-1);//申请空间并且将其数据置为-1head-next head;//将next指向headhead-prev head;//prev也是指向头的return head;//返回头申请好的空间
} 此处因为有了头那就不再需要先去创建一个链表的结构ListNode *STL NULL 来确定链表的头了不用传STL/STL、而是直接传head即可找到链表并且修改链表即使是改变链表的开始也不用再使用二级指针了。
下面的头插、头删中的头并不是头而是表示插入/删除第一个节点 2.3双向链表中放入数据 头插思路先记录通过head找到的原本的头再创建一个新节点改变链接关系即可完成
void ListPushFront(ListNode* pHead, LTDataType x)
{assert(pHead);//判空ListNode* newnode BuyMemory(x);//创建新节点ListNode* frist pHead-next;//记录原本的链表的第一个数据//改变链接关系// phead - first// phead - newnode - first//先改变newnode与第一个数据间的关系// newnode - firestnewnode-next frist; frist-prev newnode;//再改变新节点个head的链接关系// head - newnodenewnode-prev pHead;pHead-next newnode;//改完后 phead - newnode - frist
} 尾插方法和头插类似先记录尾部数据然后新建一个节点改变head、尾部数据、新节点三者的链接关系 void ListPushBack(ListNode* pHead, LTDataType x)
{assert(pHead);ListNode* newnode BuyMemory(x);//创建新节点ListNode* tail pHead-prev;//记录原本的尾部数据结构//原本的链接顺序tail - head//改变后的链接顺序tail - newnode - head//先改变 tail - newnodetail-next newnode;newnode-prev tail;//再把newnode和head链接起来newnode-headnewnode-next pHead; pHead-prev newnode;
} 在在pos位置插入数据因为这是一个双向且循环的链表所以我们只需要写一个插入接口即可实现所有想要的结果此处实现在pos位置前面插入数据其实现方法和上面的都几乎一样。 void ListInsert(ListNode* pos, LTDataType x)
{assert(pos);//判空ListNode* prev pos-prev;//记录前面的数据ListNode* newnode BuyMemory(x);//创建新节点//改变链接关系// prev pos// prev newnode pos// prev newnode prev-next newnode;newnode-prev prev;// newnode posnewnode-next pos;pos-prev newnode;// prev newnode pos
} 同样的为了获取pos的结构的空间地址我们需要写一个查找的接口 ListNode* ListFind(ListNode* pHead, LTDataType x)
{assert(pHead);ListNode* tail pHead;//tail指向链表while (tail)//通过tail指针来找{if (tail-data x)//找结构中的值是不是等于x{return tail;//找到后返回节点的地址}tail tail-next;//往后走}printf(不存在,找不到\n); //若到了此处就表示链表中的数据没有xreturn NULL;//此时返回NULL表示不存在该数据的节点
} 2.4双向链表中的删除数据
在我们删除数据的前提是得链表中有数据所以就需要一个判断是否有数据的接口
bool If_DTLEmpty(ListNode* pHead)//返回bool值,即返回真或假
{if (pHead-next pHead)//就判断phead的-是不是自己即可因为如果不是则表示是有数据的反之因为是循环链表没数据就会指向自己了{return true;//若指向自己则是真 空的}else{return false;//反之则非空}
} 头删记录第一、二个节点改变链接关系即可 void ListPopFront(ListNode* pHead)
{assert(pHead);assert(!If_DTLEmpty(pHead));//判断是否为空ListNode* front pHead-next;//记录第一个节点ListNode* frist pHead-next-next;//记录第二个节点//改变链接关系// head - front - frist head - firstpHead-next frist;frist-prev pHead;free(front);//改变链接关系后把第一个节点释放front NULL;
} 尾删记录倒数第一、二个节点改变链接关系即可 void ListPopBack(ListNode* pHead)
{assert(pHead);assert(!If_DTLEmpty(pHead));//判断是否为空ListNode* new_tail pHead-prev-prev;//记录倒数第二个节点ListNode* old_tail pHead-prev;//记录倒数第一个节点//改变链接关系new_tail-next pHead;pHead-prev new_tail;free(old_tail);//释放倒数第一个节点old_tail NULL;
} 删除指定pos位置处的数据记录pos位置的next和prev节点然后改变链接关系即可 void ListErase(ListNode* pos)
{assert(pos);//判空ListNode* prev pos-prev;//记录pos前面节点ListNode* tail pos-next;//记录pos后面的节点//改变链接关系prev-next tail;tail-prev prev;//释放posfree(pos);
} 2.5双向链表的摧毁 其摧毁的方法和单链表很像但要注意他是一个循环的链表区别在于多了个头所以就可以以这个头为结束从第一个节点开始当遇到头时就表示走完一遍链表了就跳出循环最后再把head释放一下即可 void ListDestory(ListNode* pHead)
{assert(pHead);ListNode* tail pHead-prev;//从第一个节点开始while (tail ! pHead)//当没遇到头前就不断释放再往前走{ListNode* destroy tail;//记录要释放的节点地址tail tail-next;//tail往后走free(destroy);//释放空间}free(pHead);//最后当把链表中的数据释放完后再释放头
} 2.6打印双向链表中的各个数据 从第一个节点开始遍历链表当循环回来到head时就退出 void ListPrint(ListNode* pHead)
{assert(pHead);ListNode* cur pHead-next;//从第一个节点开始printf(《》head《》);while (cur ! pHead)//当不是pHead就进去{printf(%d《》, cur-data);//打印cur cur-next;//往后走}printf(\n);
} 3.如何快速的实现一个链表 其实如果要快速的实现一个链表的话用到的就是双向循环链表因为其是双向的这样就可以直接通过在pos位置插入/删除,这样我们就能剩下写头插、删、尾插、删的时间直接通过插入/删除接口间接实现。 ListNode* BuyMemory(LTDataType x)//申请空间的函数
{ListNode* node (ListNode*)malloc(sizeof(ListNode));//malloc申请一个大小为一个结构体一个节点的空间if (node NULL)//若申请失败{perror(malloc::BuyMemory);//报错//return NULL;exit(-1);//直接退出程序}node-data x;//将申请中的空间数据置为给定的xnode-next NULL;//将next先置为NULLnode-prev NULL;//将prev先置为NULLreturn node;//返回借号的空间
}ListNode* ListCreate()//给头申请空间并且返回头指针的地址
{ListNode* head BuyMemory(-1);//申请空间并且将其数据置为-1head-next head;//将next指向headhead-prev head;//prev也是指向头的return head;//返回头申请好的空间
}void ListPushBack(ListNode* pHead, LTDataType x)
{assert(pHead);ListInsert(pHead,x);
}void ListPrint(ListNode* pHead)
{assert(pHead);ListNode* cur pHead-next;//从第一个节点开始printf(《》head《》);while (cur ! pHead)//当不是pHead就进去{printf(%d《》, cur-data);//打印cur cur-next;//往后走}printf(\n);
}bool If_DTLEmpty(ListNode* pHead)//返回bool值,即返回真或假
{if (pHead-next pHead)//就判断phead的-是不是自己即可因为如果不是则表示是有数据的反之因为是循环链表没数据就会指向自己了{return true;//若指向自己则是真 空的}else{return false;//反之则非空}}void ListPopBack(ListNode* pHead)
{assert(pHead);assert(!If_DTLEmpty(pHead));//判断链表是否为空ListErase(pHead-prev);
}void ListPushFront(ListNode* pHead, LTDataType x)
{assert(pHead);//判空ListInsert(pHead-next,x);
}void ListPopFront(ListNode* pHead)
{assert(pHead);assert(!If_DTLEmpty(pHead));//判断是否为空ListErase(pHead-next);
}ListNode* ListFind(ListNode* pHead, LTDataType x)
{assert(pHead);ListNode* tail pHead;//tail指向链表while (tail)//通过tail指针来找{if (tail-data x)//找结构中的值是不是等于x{return tail;//找到后返回节点的地址}tail tail-next;//往后走}printf(不存在,找不到\n); //若到了此处就表示链表中的数据没有xreturn NULL;//此时返回NULL表示不存在该数据的节点
}void ListInsert(ListNode* pos, LTDataType x)
{assert(pos);//判空ListNode* prev pos-prev;//记录前面的数据ListNode* newnode BuyMemory(x);//创建新节点//改变链接关系// prev pos// prev newnode pos// prev newnode prev-next newnode;newnode-prev prev;// newnode posnewnode-next pos;pos-prev newnode;// prev newnode pos
}void ListErase(ListNode* pos)
{assert(pos);//判空ListNode* prev pos-prev;//记录pos前面节点ListNode* tail pos-next;//记录pos后面的节点//改变链接关系prev-next tail;tail-prev prev;//释放posfree(pos);
}void ListDestory(ListNode* pHead)
{assert(pHead);ListNode* tail pHead-prev;//从第一个节点开始while (tail ! pHead)//当没遇到头前就不断释放再往前走{ListNode* destroy tail;//记录要释放的节点地址tail tail-next;//tail往后走free(destroy);//释放空间}free(pHead);//最后当把链表中的数据释放完后再释放头
} 如果有任何问题欢迎讨论哈
如果觉得这篇文章对你有所帮助的话点点赞吧
持续更新大量数据结构细致内容早关注不迷路。
文章转载自: http://www.morning.byjwl.cn.gov.cn.byjwl.cn http://www.morning.swsrb.cn.gov.cn.swsrb.cn http://www.morning.qgtbx.cn.gov.cn.qgtbx.cn http://www.morning.qxwgx.cn.gov.cn.qxwgx.cn http://www.morning.btwlp.cn.gov.cn.btwlp.cn http://www.morning.mftdq.cn.gov.cn.mftdq.cn http://www.morning.tjcgl.cn.gov.cn.tjcgl.cn http://www.morning.nzcgj.cn.gov.cn.nzcgj.cn http://www.morning.mdwb.cn.gov.cn.mdwb.cn http://www.morning.rqxmz.cn.gov.cn.rqxmz.cn http://www.morning.dlhxj.cn.gov.cn.dlhxj.cn http://www.morning.ypdmr.cn.gov.cn.ypdmr.cn http://www.morning.cwrnr.cn.gov.cn.cwrnr.cn http://www.morning.fhrgk.cn.gov.cn.fhrgk.cn http://www.morning.gcfg.cn.gov.cn.gcfg.cn http://www.morning.bcdqf.cn.gov.cn.bcdqf.cn http://www.morning.hybmz.cn.gov.cn.hybmz.cn http://www.morning.chzbq.cn.gov.cn.chzbq.cn http://www.morning.cnfjs.cn.gov.cn.cnfjs.cn http://www.morning.qhnmj.cn.gov.cn.qhnmj.cn http://www.morning.lkbkd.cn.gov.cn.lkbkd.cn http://www.morning.qsmmq.cn.gov.cn.qsmmq.cn http://www.morning.fcpjq.cn.gov.cn.fcpjq.cn http://www.morning.hytqt.cn.gov.cn.hytqt.cn http://www.morning.bfkrf.cn.gov.cn.bfkrf.cn http://www.morning.kstgt.cn.gov.cn.kstgt.cn http://www.morning.jkpnm.cn.gov.cn.jkpnm.cn http://www.morning.dnydy.cn.gov.cn.dnydy.cn http://www.morning.gbcnz.cn.gov.cn.gbcnz.cn http://www.morning.wttzp.cn.gov.cn.wttzp.cn http://www.morning.rfkyb.cn.gov.cn.rfkyb.cn http://www.morning.ndngj.cn.gov.cn.ndngj.cn http://www.morning.yongkangyiyuan-pfk.com.gov.cn.yongkangyiyuan-pfk.com http://www.morning.crxdn.cn.gov.cn.crxdn.cn http://www.morning.rlqml.cn.gov.cn.rlqml.cn http://www.morning.mnjyf.cn.gov.cn.mnjyf.cn http://www.morning.jsljr.cn.gov.cn.jsljr.cn http://www.morning.dzpnl.cn.gov.cn.dzpnl.cn http://www.morning.jbxmb.cn.gov.cn.jbxmb.cn http://www.morning.wjqyt.cn.gov.cn.wjqyt.cn http://www.morning.xknsn.cn.gov.cn.xknsn.cn http://www.morning.zrnph.cn.gov.cn.zrnph.cn http://www.morning.rcrnw.cn.gov.cn.rcrnw.cn http://www.morning.bkryb.cn.gov.cn.bkryb.cn http://www.morning.dncgb.cn.gov.cn.dncgb.cn http://www.morning.wspjn.cn.gov.cn.wspjn.cn http://www.morning.jyzxt.cn.gov.cn.jyzxt.cn http://www.morning.kbfzp.cn.gov.cn.kbfzp.cn http://www.morning.jlxqx.cn.gov.cn.jlxqx.cn http://www.morning.grbp.cn.gov.cn.grbp.cn http://www.morning.bsbcp.cn.gov.cn.bsbcp.cn http://www.morning.tpchy.cn.gov.cn.tpchy.cn http://www.morning.rcww.cn.gov.cn.rcww.cn http://www.morning.jfjbl.cn.gov.cn.jfjbl.cn http://www.morning.mdlqf.cn.gov.cn.mdlqf.cn http://www.morning.bdwqy.cn.gov.cn.bdwqy.cn http://www.morning.lbywt.cn.gov.cn.lbywt.cn http://www.morning.lxngn.cn.gov.cn.lxngn.cn http://www.morning.fnjrh.cn.gov.cn.fnjrh.cn http://www.morning.jcwhk.cn.gov.cn.jcwhk.cn http://www.morning.lizpw.com.gov.cn.lizpw.com http://www.morning.yunease.com.gov.cn.yunease.com http://www.morning.hyryq.cn.gov.cn.hyryq.cn http://www.morning.dfbeer.com.gov.cn.dfbeer.com http://www.morning.msxhb.cn.gov.cn.msxhb.cn http://www.morning.mfltz.cn.gov.cn.mfltz.cn http://www.morning.tscsd.cn.gov.cn.tscsd.cn http://www.morning.ywtbk.cn.gov.cn.ywtbk.cn http://www.morning.qflwp.cn.gov.cn.qflwp.cn http://www.morning.qzqfq.cn.gov.cn.qzqfq.cn http://www.morning.rbnnq.cn.gov.cn.rbnnq.cn http://www.morning.sfsjh.cn.gov.cn.sfsjh.cn http://www.morning.wlddq.cn.gov.cn.wlddq.cn http://www.morning.hxwrs.cn.gov.cn.hxwrs.cn http://www.morning.yqhdy.cn.gov.cn.yqhdy.cn http://www.morning.qkgwx.cn.gov.cn.qkgwx.cn http://www.morning.mmjqk.cn.gov.cn.mmjqk.cn http://www.morning.prmbn.cn.gov.cn.prmbn.cn http://www.morning.lcdtb.cn.gov.cn.lcdtb.cn http://www.morning.mlnby.cn.gov.cn.mlnby.cn