线性表->链式存储->线形链表(单链表)
文字描述:
为了表示前后两个数据元素的逻辑关系,对于每个数据元素,除了存储其本身的信息之外(数据域),还需存储一个指示其直接后继的信息(即直接后继的存储位置,指针域)。
示意图:
算法分析:
在单链表中插入和删除元素时,主要是改变指针的值,其时间复杂度为1。而顺序存储的话,其时间复杂度为n。
在单链表中求长度时不如顺序存储结构,其时间复杂度为n; 而顺序存储是1。故可以在链表头结点中设置一个长度值,在插入数据元素时加1,在删除数据元素时减1。
在单链表中查找指定数据元素时,其时间复杂度和顺序存草时一样,乱序情况下为n。
代码实现(动态单链表):
//
// Created by lady on 19-1-26.
// #include <stdlib.h>
#include <stdio.h>
#include <string.h> //线性表的动态单链表存储结构
typedef struct ElemType{
char data[];
}ElemType;
typedef struct LNode{
ElemType e;
struct LNode *next;
}LNode, *LinkList; /*
* 倒序法输入n个元素的值,建立带表头结点的单链表线性表L
*/
static int CreateList_L(LinkList *L, int n, char name[])
{
printf("以倒插入法创建单链表存储结构的线性表%s:\n", name);
//先建立一个带头结点的单链表
if((*L=(LinkList)malloc(sizeof(LNode))) == NULL){
return -;
}
(*L)->next = NULL;
int i = ;
LinkList p = NULL;
for(i=n; i>; --i){
//生成新的结点
p = (LinkList)malloc(sizeof(LNode));
//输入元素值
printf("输入第%d个元素:", i);
scanf("%s[^\\n]", p->e.data);
//插入到表头
p->next = (*L)->next;
(*L)->next = p;
}
return ;
} /*依次对L的每个数据元素调用函数fun。一旦fun失败,则操作失败*/
static int ListTraverse_L(LinkList L, int (*fun)(ElemType,int), char info[])
{
printf("%s", info);
//跳过头结点
LNode *p = L->next;
int i = ;
while(p){
if(fun(p->e, i++)){
printf("Err:when traverse(e,%d) wrong!\n",i);
}
p = p->next;
}
printf("\n");
} /*
* L为带头结点的单链表的头指针
* 当第i个元素存在是,其值赋给e并返回0,否则返回-1
*/
static int GetElem_L(LinkList L, int i, ElemType *e)
{
//初始化,p指向第一个结点
LNode *p = L->next;
//j为计数器
int j = ;
while(p && j<i){
//顺指针向后查找,知道p指向第i个元素或者p为空
p = p->next;
j+=;
}
if(!p || j>i){
//第i个元素不存在
return -;
}
//取第i个元素
*e = p->e;
return ;
} /*
* 在带头结点的单链表线性表L中第i个位置之前插入元素e
*/
static int ListInsert_L(LinkList *L, int i, ElemType e)
{
LNode *p = (LNode *)(*L);
int j = ;
while(p && j<i-){
//寻找第i-1个结点
p = p->next;
++j;
}
//i小于1或者大于表长+1
if(!p || j>i)
return -;
//生成新的结点
LinkList s = (LinkList)malloc(sizeof(LNode));
s->e = e;
//将新结点插入到链表L中
s->next = p->next;
p->next = s;
return ;
} /*
* 在带头结点的单链线性表L中,删除第i个元素,并有e返回其值
*/
static int ListDelete_L(LinkList *L, int i, ElemType *e)
{
LNode *p = (LNode *)(*L);
LNode *q = NULL;
int j = ;
while(p->next && (j<i-)){
//寻找第i个结点,并令p指向其前趋
p = p->next;
++j;
}
if(!(p->next) || (j>i-)){
//删除位置不合理
return -;
}
//删除该结点
q = p->next;
p->next = q->next;
*e = q->e;
//释放该结点的占用空间
free(q);
return ;
} /*
* 输入元素e的数据和位置
*/
static int printE(ElemType e, int location)
{
printf("%3d=%-10s", location, e.data);
return ;
} /*
* 已知单链线性表La和Lb的元素按值非递减排列
* 归并La和Lb得到新的单链线性表Lc,Lc的元素也按值非递减排列
*/
static void MergeList_L(LinkList La, LinkList Lb, LinkList *Lc)
{
LNode *pa = La->next;
LNode *pb = Lb->next;
LNode *pc = NULL;
LNode *p;
//用La的头结点作为Lc的头结点
pc = (LNode*)La;
*Lc = La; while(pa && pb){
if(atoi(pa->e.data) <= atoi(pb->e.data)){
//需要将当前的pa结点插入到pc结点
if(pc->next == pa){
//pc结点正好在pa链表
pc = pc->next;//移动pc结点到下一个结点
pa = pa->next;//移动pa结点到下一个结点
}else{
//需要将pa结点插入到pc结点后,插入后pc、pa结点要后移动
p = pa;
pa = pa->next;
p->next = pc->next;
pc->next = p;
pc = pc->next;
}
}else{
if(pc->next == pb){
pc = pc->next;
pb = pb->next;
} else{
p = pb;
pb = pb->next;
p->next = pc->next;
pc->next = p;
pc = pc->next;
}
}
}
//插入剩余段
pc->next = pa?pa:pb;
//释放Lb的头结点
free(Lb);
} /*
* 释放链表L
*/
static int DestoryList_L(LinkList *L)
{
if(L == NULL){
return -;
}
if(*L == NULL){
return -;
}
LNode *p, *q;
p = (LNode*)(*L);
while(p){
q = p;
free(q);
p = p->next;
}
*L = NULL;
return ;
} int main(int argc, char *argv[])
{ ElemType e;
int location = ; LinkList L;
CreateList_L(&L, , "L");
ListTraverse_L(L, printE, "L:"); printf("insert a data and print, please input (location, data):");
scanf("%d,%s[^\\n]", &location, e.data);
ListInsert_L(&L, location, e);
ListTraverse_L(L, printE, "L:");
printf("\n"); printf("delete a data through location and print, please input (location):");
scanf("%d[^\\n]", &location);
ListDelete_L(&L, location, &e);
printf("location %d, data %s is deleted from List\n", location, e.data);
ListTraverse_L(L, printE, "init:");
printf("\n"); printf("locate/find a data through location, please input (location):");
scanf("%d[^\\n]", &location);
GetElem_L(L, location, &e);
printf("the data of what location is %d, is %s\n", location, e.data);
printf("\n"); printf("Merge LA and LB to LC!\n");
LinkList La, Lb, Lc;
//create La
CreateList_L(&La, , "La");
ListTraverse_L(La, printE, "La:");
//create Lb
CreateList_L(&Lb, , "Lb");
ListTraverse_L(Lb, printE, "Lb:");
//merge La and Lb to Lc
MergeList_L(La, Lb, &Lc);
ListTraverse_L(Lc, printE, "Lc:"); DestoryList_L(&L);
DestoryList_L(&La);
DestoryList_L(&Lb);
}
动态单链表
代码运行(动态单链表):
/home/lady/CLionProjects/untitled/cmake-build-debug/untitled
以倒插入法创建单链表存储结构的线性表L:
输入第4个元素:ZHAO
输入第3个元素:QIAN
输入第2个元素:SUN
输入第1个元素:LI
L: 1=LI 2=SUN 3=QIAN 4=ZHAO
insert a data and print, please input (location, data):2,ZHOU
L: 1=LI 2=ZHOU 3=SUN 4=QIAN 5=ZHAO delete a data through location and print, please input (location):3
location 3, data SUN is deleted from List
init: 1=LI 2=ZHOU 3=QIAN 4=ZHAO locate/find a data through location, please input (location):3
the data of what location is 3, is QIAN Merge LA and LB to LC!
以倒插入法创建单链表存储结构的线性表La:
输入第4个元素:11
输入第3个元素:8
输入第2个元素:5
输入第1个元素:3
La: 1=3 2=5 3=8 4=11
以倒插入法创建单链表存储结构的线性表Lb:
输入第7个元素:20
输入第6个元素:15
输入第5个元素:11
输入第4个元素:9
输入第3个元素:8
输入第2个元素:6
输入第1个元素:2
Lb: 1=2 2=6 3=8 4=9 5=11 6=15 7=20
Lc: 1=2 2=3 3=5 4=6 5=8 6=8 7=9 8=11 9=11 10=15 11=20 Process finished with exit code 0
代码实现(带头结点的单向动态链表)
#include <stdio.h>
#include <stdlib.h>
#include <string.h> //带头结点的线性链表类型定义如下
typedef struct ElemType{
char data[];
}ElemType;
typedef struct LNode{//结点类型
ElemType e;
struct LNode *next;
}*Link, *Position;
typedef struct {//链表类型
Link head,tail;//分别指向线性链表中的头结点和最后一个结点
int len;//指示线性链表中数据元素的个数
}LinkList; /*
*依次对L的每个元素调用visit函数,一旦失败,则操作失败
*/
static int ListTraverse(LinkList L, int (*visit)(ElemType,int), const char note[])
{
printf("遍历线性表%s:", note);
Link p = L.head->next;
int i = ;
while(p){
if(visit(p->e,i)<){
return -;
}
if(p==L.tail)
break;
p = p->next;
}
printf("\n");
return ;
} static int print(ElemType e, int loc)
{
printf("%3d=%-6s", loc, e.data);
return ;
} //构造一个空的线性链表L
static int InitList(LinkList *L)
{
if(L==NULL){
return -;
}
Link p = (Link)malloc(sizeof(struct LNode));
memset(p->e.data, , sizeof(p->e.data));
p->next = p;
L->len = ;
L->head = L->tail = p;
return ;
} //返回p指示线性链表L中第i个结点的位置并返回0 i值不合法时返回-1
static int LocatePos(LinkList *L, int i, Link *p)
{
if(L==NULL || p==NULL){
return -;
}
*p=L->head;
int index = ;
while((index<L->len) && (*p != L->tail)){
(*p) = (*p)->next;
index +=;
if(index == i)
break;
}
return (index==i)?:-;
} //创建一个值为e的结点, 其地址为p; 成功则返回0, 失败就返回-1
static int MakeNode(Link *p, ElemType e)
{
if(p==NULL){
return -;
}
if(((*p) = (Link)malloc(sizeof(struct LNode))) == NULL){
return -;
}
(*p)->next = NULL;
(*p)->e = e;
return ;
} //已知h指向线性链表的头结点,将s所指结点插入在第一个结点之前
static int InsFirst(Link *h, Link *s)
{
if(h==NULL || s==NULL){
return -;
}
if(*h == NULL || *s == NULL){
return -;
}
(*s)->next = (*h)->next;
(*h)->next = (*s);
return ;
} //在带头结点的单链线性表L的第i个元素之前插入元素e
static int ListInsert_L(LinkList *L, int i, ElemType e)
{
Link h = NULL;
Link p = NULL;
if(LocatePos(L, i-, &h)<){
//i值不合法
return -;
}
if(MakeNode(&p, e)<){
//结点存储分配失败
return -;
}
//对于从第i个结点开始的链表,第i-1个结点是它的头结点
InsFirst(&h, &p);
//如果是在链表的最后一个结点上插入, 那么和改变链表的尾结点指针
if(L->tail == h){
p->next = L->head;
L->tail = p;
}
//链表长度+1
L->len += ;
return ;
} //创建一个长度为n的带头结点的单项链表L
static int CreateList(LinkList *L, int n, char note[])
{
printf("创建一个长度为%d的带头结点的单向线性链表%s!\n", n, note);
if(L==NULL){
return -;
}
if(InitList(L)<){
return -;
}
ElemType e;
int i = ;
for(i=; i<=n; i++){
printf("输入第%d个元素:", i);
scanf("%s[^\\n]", e.data);
if(ListInsert_L(L, i, e)<){
return -;
}
}
} //返回链表L的头结点
static Link GetHead(LinkList *L){
if(L==NULL){
return NULL;
}
return L->head;
} //返回链表L中结点p的后继
static Link NextPos(LinkList *L, Link p)
{
if(L == NULL || p==NULL){
return NULL;
}
return p->next;
} //返回结点p中的数据元素
static ElemType GetCurElem(Link p)
{
return p->e;
} //释放结点p
static void FreeNode(Link p)
{
if(p)
free(p);
return;
} //将指针s所指的一串结点连接到线性链表L的最后一个结点
static int Append(LinkList *L, Link *s)
{
if(L == NULL || s==NULL || *s==NULL){
return -;
}
L->tail->next = (*s);
Link p = *s;
Link t = p;
int count = ;
while(p){
count += ;
t = p;
p = p->next;
}
L->len += count;
t->next = L->head;
L->tail = t;
return ;
} //已知h指向线性链表的头结点,删除链表中的第一个结点并以求返回
static int DelFirst(Link *h, Link *q)
{
if(h==NULL || q==NULL){
return -;
}
if(*h == NULL || *q == NULL){
return -;
}
(*q) = (*h)->next;
(*h)->next = (*q)->next;
(*q)->next = NULL;
return ;
} //已知单链线性表La和Lb的元素按值非递减排列
//归并La和Lb得到新的单链线性表Lc Lc的元素也按值非递减排列
static int MergeList_L(LinkList *La, LinkList *Lb, LinkList *Lc, int (*compare)(ElemType,ElemType),const char note[])
{
printf("%s\n", note);
if(InitList(Lc)<){
//存储空间分配失败
return -;
}
Link ha = GetHead(La);//ha指向La的头结点
Link hb = GetHead(Lb);//hb指向Lc的头结点
if(ha==NULL || hb==NULL){
return -;
}
Link pa = NextPos(La, ha);//pa指向La中第一个结点
Link pb = NextPos(Lb, hb);//pb指向Lb中第一个结点
Link p; ElemType a;
ElemType b; Link q;
while(pa && pb){
//La和Lb均非空
//a和b为两表中当前比较元素
a = GetCurElem(pa);
b = GetCurElem(pb);
if(compare(a, b)<=){//a<=b
DelFirst(&ha, &q);
Append(Lc, &q);
if(pa == La->tail){
pa = NULL;
break;
}
pa = NextPos(La, ha);
}else{//a>b
DelFirst(&hb, &q);
Append(Lc, &q);
if(pb == Lb->tail){
pb = NULL;
break;
}
pb = NextPos(Lb, hb);
}
}
if(pa){
//链接La中剩余结点
p = pa;
while(p){
if(p == La->tail){
p->next = NULL;
break;
}
p = p->next;
}
Append(Lc, &pa);
}else{
//链接Lb中剩余结点
p = pb;
while(p){
if(p == Lb->tail){
p->next = NULL;
break;
}
p = p->next;
}
Append(Lc, &pb);
}
//释放La和Lb的头结点
FreeNode(ha);
FreeNode(hb);
return ;
} /*
* 将元素a和b转换成整数a和整数b
* 返回-1:整数a > 整数b
* 返回0:整数a = 整数b
* 返回1:整数a < 整数b
*/
static int compare(ElemType a, ElemType b)
{
int i_a = atoi(a.data);
int i_b = atoi(b.data);
if(i_a<i_b){
return -;
}else if(i_a == i_b){
return ;
}else{
return ;
}
} int main(int argc, char *argv[])
{
LinkList La; //3,5,8,11
LinkList Lb; //2,6,8,9,11,15,20
if((CreateList(&La, , "La")<) || (ListTraverse(La, print, "La")<)){
return -;
}
if((CreateList(&Lb, , "Lb")<) || (ListTraverse(Lb, print, "Lb")<)){
return -;
}
LinkList Lc;
if((MergeList_L(&La, &Lb, &Lc, compare, "归并La和Lb到Lc!")<) || (ListTraverse(Lc, print, "Lc")<)){
return -;
}
return ;
}
带头结点的单项动态链表
代码运行(带头结点的单向动态链表)
/home/lady/CLionProjects/untitled/cmake-build-debug/untitled
创建一个长度为4的带头结点的单向线性链表La!
输入第1个元素:3
输入第2个元素:5
输入第3个元素:8
输入第4个元素:11
遍历线性表La: 1=3 1=5 1=8 1=11
创建一个长度为7的带头结点的单向线性链表Lb!
输入第1个元素:2
输入第2个元素:6
输入第3个元素:8
输入第4个元素:9
输入第5个元素:11
输入第6个元素:15
输入第7个元素:20
遍历线性表Lb: 1=2 1=6 1=8 1=9 1=11 1=15 1=20
归并La和Lb到Lc!
遍历线性表Lc: 1=2 1=3 1=5 1=6 1=8 1=8 1=9 1=11 1=11 1=15 1=20 Process finished with exit code 0
代码实现(静态单链表):
//
// Created by lady on 19-1-27.
// #include <stdio.h>
#include <stdlib.h>
#include <string.h> //---------------线性表的静态单链表存储结构-----------
#define MAXSIZE 12 //链表的最大长度
typedef struct ElemType{
char data[];
}ElemType;
typedef struct{
ElemType e;
int cur;
}component,SLinkList[MAXSIZE]; /*
* 依次打印静态链表space中的数据
*/
static void Debug_Print(SLinkList space, char note[])
{
printf("%s\n", note);
int i = ;
for(i=; i<MAXSIZE; i++){
printf("\tindex %-5d[data:%-5s,cur:%-2d]\n", i, space[i].e.data, space[i].cur);
}
} /*
* 将一维数组space中各分量链成一个备用链表,space[0].cur为头指针, “0”表示空指针。
*/
static void InitSpace_SL(SLinkList space)
{
int i = ;
for(i=; i<MAXSIZE-; ++i){
memset(space[i].e.data, , sizeof(space[i].e.data));
space[i].cur = i+;
}
memset(space[MAXSIZE-].e.data, , sizeof(space[MAXSIZE-].e.data));
space[MAXSIZE-].cur = ;
return ;
} /*
* 如果备用空间链表非空,则返回分配的结点下标,否则返回0
*/
static int Malloc_SL(SLinkList space)
{
int i = ;
i = space[].cur;
if(space[].cur)
space[].cur = space[i].cur;
return i;
} /*
* 将下标为k的空闲结点回收到备用链表。
*/
static int Free_SL(SLinkList space, int k)
{
space[k].cur = space[].cur;
space[].cur = k;
return ;
} /*
* 依次输入集合A和B的元素,在一维数组space中建立表示集合 (A-B)U(B-A)的静态链表,S为其头指针。
* 假设备用空间够大,space[0].cur为备用空间的头指针
*/
static void difference(SLinkList space, int *S)
{
printf("用静态链表算集合(A-B)U(B-A):\n");
InitSpace_SL(space); //将space整个初始化成备用空间
(*S) = Malloc_SL(space);//生成S的头结点
int r = *S;//r始终指向静态链表S的最后一个元素。
int m, n;
int i, j;
char str[] = {};
printf("step1\t:依次输入A和B集合的元素个数(m,n):");
scanf("%d,%d[^\\n]", &m, &n);
printf("step2.1\t:依次输入A中的元素到集合S:\n");
for(j=; j<=m; ++j){
i = Malloc_SL(space);
printf("\t输入A中第%d/%d个元素:", j, m);
scanf("%s[^\\n]", space[i].e.data);
//插入到表尾巴
space[r].cur = i;
r = i;
}
space[r].cur = ;
Debug_Print(space, "step2.2\t:创建集合A后的集合S值"); printf("step3\t:依次输入B中的元素,同时查找S表,如果已经存在则从S中删除之,否则加入到S!\n");
ElemType b;
int p;
int k;
for(j=; j<=n; ++j){
memset(b.data, , sizeof(b.data));
printf("\t输入B中第%d/%d个元素:", j, n);
scanf("%s[^\\n]", b.data);
p = (*S);
k = space[p].cur; //k指向集合A中第一个结点
while(k!=space[r].cur && strncmp(space[k].e.data, b.data, sizeof(b.data))){
//在当前表中查找
p = k;
k = space[k].cur;
}
if(k == space[r].cur){
//当前表中不存在该元素, 插入在r所值结点后,且r的位置不变。
i = Malloc_SL(space);
space[i].e = b;
space[i].cur = space[r].cur;
space[r].cur = i;
snprintf(str, sizeof(str), "step3.1\t:元素%s在S中不存在,插入之!",b.data);
Debug_Print(space, str);
}else{
//该元素已在表中,则删除之
space[p].cur = space[k].cur;
Free_SL(space, k);
if(r == k){
//如果删除的是r所指结点,则需修改尾指针。
r = p;
}
snprintf(str, sizeof(str), "step3.1\t:元素%s在S中存在,删除之!",b.data);
Debug_Print(space, str);
}
}
} int main(int argc, char *argv[])
{
SLinkList space;
int s;
//求(A-B)U(B-A)
difference(space, &s);
return ;
}
静态链表
代码运行(静态单链表):
/home/lady/CLionProjects/untitled/cmake-build-debug/untitled
用静态链表算集合(A-B)U(B-A):
step1 :依次输入A和B集合的元素个数(m,n):6,4
step2.1 :依次输入A中的元素到集合S:
输入A中第1/6个元素:c
输入A中第2/6个元素:b
输入A中第3/6个元素:e
输入A中第4/6个元素:g
输入A中第5/6个元素:f
输入A中第6/6个元素:d
step2.2 :创建集合A后的集合S值
index 0 [data: ,cur:8 ]
index 1 [data: ,cur:2 ]
index 2 [data:c ,cur:3 ]
index 3 [data:b ,cur:4 ]
index 4 [data:e ,cur:5 ]
index 5 [data:g ,cur:6 ]
index 6 [data:f ,cur:7 ]
index 7 [data:d ,cur:0 ]
index 8 [data: ,cur:9 ]
index 9 [data: ,cur:10]
index 10 [data: ,cur:11]
index 11 [data: ,cur:0 ]
step3 :依次输入B中的元素,同时查找S表,如果已经存在则从S中删除之,否则加入到S!
输入B中第1/4个元素:a
step3.1 :元素a在S中不存在,插入之!
index 0 [data: ,cur:9 ]
index 1 [data: ,cur:2 ]
index 2 [data:c ,cur:3 ]
index 3 [data:b ,cur:4 ]
index 4 [data:e ,cur:5 ]
index 5 [data:g ,cur:6 ]
index 6 [data:f ,cur:7 ]
index 7 [data:d ,cur:8 ]
index 8 [data:a ,cur:0 ]
index 9 [data: ,cur:10]
index 10 [data: ,cur:11]
index 11 [data: ,cur:0 ]
输入B中第2/4个元素:b
step3.1 :元素b在S中存在,删除之!
index 0 [data: ,cur:3 ]
index 1 [data: ,cur:2 ]
index 2 [data:c ,cur:4 ]
index 3 [data:b ,cur:9 ]
index 4 [data:e ,cur:5 ]
index 5 [data:g ,cur:6 ]
index 6 [data:f ,cur:7 ]
index 7 [data:d ,cur:8 ]
index 8 [data:a ,cur:0 ]
index 9 [data: ,cur:10]
index 10 [data: ,cur:11]
index 11 [data: ,cur:0 ]
输入B中第3/4个元素:n
step3.1 :元素n在S中不存在,插入之!
index 0 [data: ,cur:9 ]
index 1 [data: ,cur:2 ]
index 2 [data:c ,cur:4 ]
index 3 [data:n ,cur:8 ]
index 4 [data:e ,cur:5 ]
index 5 [data:g ,cur:6 ]
index 6 [data:f ,cur:7 ]
index 7 [data:d ,cur:3 ]
index 8 [data:a ,cur:0 ]
index 9 [data: ,cur:10]
index 10 [data: ,cur:11]
index 11 [data: ,cur:0 ]
输入B中第4/4个元素:f
step3.1 :元素f在S中存在,删除之!
index 0 [data: ,cur:6 ]
index 1 [data: ,cur:2 ]
index 2 [data:c ,cur:4 ]
index 3 [data:n ,cur:8 ]
index 4 [data:e ,cur:5 ]
index 5 [data:g ,cur:7 ]
index 6 [data:f ,cur:9 ]
index 7 [data:d ,cur:3 ]
index 8 [data:a ,cur:0 ]
index 9 [data: ,cur:10]
index 10 [data: ,cur:11]
index 11 [data: ,cur:0 ] Process finished with exit code 0
线性表->链式存储->线形链表(单链表)的更多相关文章
- c数据结构 -- 线性表之 顺序存储结构 于 链式存储结构 (单链表)
线性表 定义:线性表是具有相同特性的数据元素的一个有限序列 类型: 1:顺序存储结构 定义:把逻辑上相邻的数据元素存储在物理上相邻的存储单元中的存储结构 算法: #include <stdio. ...
- 线性表->链式存储->双向链表
文字描述 之前的链表(单链表.循环链表)的链式存储结构中只有一个指示直接后继的指针域.由此,从某个结点出发只能顺指针往后寻查其他结点.若要寻查结点的直接前驱,则需从表头指针出发.即单链表中,NextE ...
- 线性表->链式存储->循环链表
文字描述 循环链表是另一种形式的链式存储结构.它的特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环.由此,从表中任一结点出发均可找到表中其他结点. 示意图 算法分析 插入.删除.查找等同单 ...
- C++实现线性表的链接存储结构(单链表)
将线性表的抽象数据类型定义在链接存储结构下用C++的类实现,由于线性表的数据元素类型不确定,所以采用模板机制. 头文件linklist.h #pragma once #include <iost ...
- C语言实现线性表(链式存储方式)
#include <stdio.h> #include <stdlib.h> //提供malloc()原型 typedef struct LNode *List; typede ...
- 有一个线性表,采用带头结点的单链表L来存储,设计一个算法将其逆置,且不能建立新节点,只能通过表中已有的节点的重新组合来完成。
有一个线性表,采用带头结点的单链表L来存储,设计一个算法将其逆置,且不能建立新节点,只能通过表中已有的节点的重新组合来完成. 分析:线性表中关于逆序的问题,就是用建立链表的头插法.而本题要求不能建立新 ...
- "《算法导论》之‘线性表’":基于指针实现的单链表
对于单链表的介绍部分参考自博文数组.单链表和双链表介绍 以及 双向链表的C/C++/Java实现. 1. 单链表介绍 单向链表(单链表)是链表的一种,它由节点组成,每个节点都包含下一个节点的指针. ...
- C语言 线性表 链式表结构 实现
一个单链式实现的线性表 mList (GCC编译). /** * @brief 线性表的链式实现 (单链表) * @author wid * @date 2013-10-21 * * @note 若代 ...
- "《算法导论》之‘线性表’":基于数组实现的单链表
对于单链表,我们大多时候会用指针来实现(可参考基于指针实现的单链表).现在我们就来看看怎么用数组来实现单链表. 1. 定义单链表中结点的数据结构 typedef int ElementType; cl ...
随机推荐
- HDR拍照
HDR 拍照: (High Dynamic Range Imaging)高动态范围成像,是用来实现比普通数字图像技术更大曝光动态范围(即更大的明暗差别)的一组技术.高动态范围成像的目的就 ...
- 解决前后端分离后的Cookie跨域问题
一. 前端Ajax关键配置 $.ajax({ type: "post", url: xxx, data: xxx, contentType: 'application/json', ...
- 【转载】IIS出现“HTTP 错误 500.0,C:\php\php-cgi.exe - FastCGI 进程意外退出”解决方法
昨天给大家介绍了在windows+iis的平台上搭建支持php+mysql平台的文章,教程步骤都是笔者一步一个操作然后一个记录介绍给大家的,实机演练,教程绝对切实可用,但是不同的同学在不同的环境下按照 ...
- php 常用的自定义函数
1. 发送 SMS 在开发 Web 或者移动应用的时候,经常会遇到需要发送 SMS 给用户,或者因为登录原因,或者是为了发送信息.下面的 PHP 代码就实现了发送 SMS 的功能. 为了使用任何的语言 ...
- django日志,django-crontab,django邮件模块
django 日志 四大块,格式器,过滤器,处理器,日志管理器 LOGGING = { 'version': 1, 'disable_existing_loggers': True, 'formatt ...
- python正则表达式--编译正则表达式re.compile
编译正则表达式-- re.compile 使用re的一般步骤是先将正则表达式的字符串形 式编译为pattern实例,然后使用pattern实例处理文本并获取匹配结果(一个Match实例(值为True) ...
- JavaScript入门学习笔记(JSON)
JSON是JavaScript Object Notation的简称,是一种轻量级的数据交换格式. JSON使用JS的语法,但其格式只是一个文本,可以被任何编程语言读取病作为数据格式传递. JSON以 ...
- OpenCV-Python教程9-平滑图像
先解释一个单词 blur:使...模糊不清 滤波与模糊 滤波和模糊都属于卷积,不同的滤波方法之间只是卷积核不同(对线性滤波而言) 低通滤波器是模糊,高通滤波器是锐化 低通滤波器允许低频信号通过,在图像 ...
- CSS之链接
改变链接样式 当设置为若干链路状态的样式,也有一些顺序规则: a:hover 必须跟在 a:link 和 a:visited后面 a:active 必须跟在 a:hover后面 <!DOCTYP ...
- SQL允许脏读WITH(NOLOCK)
使用WIHT(NOLOCK)有利也有弊,所以在决定使用之前,你一定需要了解清楚WITH(NOLOCK)的功能和缺陷,看其是否适合你的业务需求,不要觉得它能提升性能,稀里糊涂的就使用它. --事务未提交 ...