双向链表每个node都有两个指针,分别指向前驱和后继。从头结点后第一个结点开始,都可以访问它的前驱结点和后继结点。
typedef struct DoubleLinkedNode{
char data;
struct DoubleLinkedNode *previous;
struct DoubleLinkedNode *next;
}DLNode,*DLNodePtr;
DLNodePtr initLinkList(){
DLNodePtr tempHeader=(DLNodePtr)malloc(sizeof(struct DoubleLinkedNode));
tempHeader->data='\0';
tempHeader->previous=NULL;
tempHeader->next=NULL;
return tempHeader;
}
void printList(DLNodePtr paraHeader){
DLNodePtr p=paraHeader->next;
while(p!=NULL){
printf("%c",p->data);
p=p->next;
}
printf("\r\n");
}
void insertElement(DLNodePtr paraHeader,char paraChar,int paraPosition){
DLNodePtr p,q,r;
p=paraHeader;
for(int i=0;i<paraPosition;i++){
p=p->next;
if(p==NULL){
printf("The position %d is beyond the scope of the list.\r\n",paraPosition);
return;
}
}
q=(DLNodePtr)malloc(sizeof(struct DoubleLinkedNode));
q->data=paraChar;
r=p->next;
q->next=p->next;
q->previous=p;
p->next=q;
if(r!=NULL){
r->previous=q;
}
}
第二步:通过循环使P找到指定位置,R指向指定位置后一个结点
第三步:Q的next指向P的next,Q的previous指向P,Q的next指向R,R的previous指向Q
void deleteElement(DLNodePtr paraHeader,char paraChar){
DLNodePtr p,q,r;
p=paraHeader;
while((p->next!=NULL)&&(p->next->data!=paraChar)){
p=p->next;
}
if(p->next==NULL){
printf("The char '%c' does not exist.\r\n",paraChar);
return;
}
q=p->next;
r=q->next;
p->next=r;
if(r!=NULL){
r->previous=p;
}
free(q);
}
第二步:通过循环使P指向指定位置,Q指向P结点后一个结点,R指向Q结点后一个结点
第三步:P的next指向R,R的previous指向P,释放Q指向的内存
void basicAddressTest(){
DLNode tempNode1,tempNode2;
tempNode1.data=4;
tempNode1.next=NULL;
tempNode2.data=6;
tempNode2.next=NULL;
printf("The first node :%d,%d,%d\r\n",&tempNode1,&tempNode1.data,&tempNode1.next);
printf("The second node :%d,%d,%d\r\n",&tempNode2,&tempNode2.data,&tempNode2.next);
tempNode1.next=&tempNode2;
}
void insertDeleteTest(){
DLNodePtr tempList=initLinkList();
printList(tempList);
insertElement(tempList,'H',0);
insertElement(tempList,'e',1);
insertElement(tempList,'l',2);
insertElement(tempList,'l',3);
insertElement(tempList,'o',4);
insertElement(tempList,'!',5);
printList(tempList);
deleteElement(tempList,'e');
deleteElement(tempList,'a');
deleteElement(tempList,'o');
//printf("YES\n");
printList(tempList);
insertElement(tempList,'o',1);
printList(tempList);
}
char get(Dnode pH,int pPos){
//判断输入是否合法
if(pPos<0){
printf("ERROR! 请输入一个大于零的数!\n");
return '\0';
}
Dnode p=pH;
int i;
//通过循环使p指向相应位置
for(i=0;i<pPos;++i){
p=p->next;
//若超过链表长度,输出原因并退出函数
if(p==NULL){
printf("ERROR! 超过限度!\n");
return'\0';
}
}
//数据合法,返回data
return p->data;
}
Dnode locate(Dnode pH,char pC){
Dnode p=pH;
通过循环定位到结点
while((p->next!=NULL)&&(p->next->data!=pC)){
p=p->next;
}
p=p->next;
//p移动到链表末端则证明未找到
//打印并退出
if(p==NULL){
printf("ERROR! 未找到!\n");
return NULL;
}
//返回p
return p;
}
void destroy(Dnode pH){
Dnode p=pH;
Dnode q=pH->next;
//通过循环依次清空
while(q!=NULL){
free(p);
p=q;
q=q->next;
//printf("YES\n");
}
free(p);
//打印提示信息
printf("DESTROY END!\n");
}
void Test(){
//创建链表
Dnode t=init();
printf("初始化 :");
printL(t);
//加入元素测试
printf("尾部添加元素 :");
inserttail(t,'c',0);
inserttail(t,'s',1) ;
inserttail(t,'d',2);
inserttail(t,'n',3);
printL(t);
//删除元素测试
printf("删除元素 :");
deleteL(t,'s');
deleteL(t,'a');
deleteL(t,'d');
printL(t);
//再次加入元素
printf("在指定元素后加入 :");
inserttail(t,'w',1);
inserttail(t,'o',2);
inserttail(t,'p',8);
printL(t);
//GET测试
char bb=get(t,2);
printf("GET : %c\n",bb);
char cc=get(t,7);
printf("GET : %c\n",cc);
//LOCATE测试
Dnode tt=locate(t,'b');
printf("LOCATE : %ld\n",tt);
Dnode mm=locate(t,'o');
printf("LOCATE : %ld\n",mm);
//DESTROY测试
destroy(t);
//打印地址
printAddress();
}
#include <stdio.h>
#include <malloc.h>
typedef struct DoubleLinknode{
char data;
struct DoubleLinknode *previous;
struct DoubleLinknode *next;
}DLnode,*Dnode;
Dnode init(){
Dnode tHeared=(Dnode)malloc(sizeof(DLnode));
tHeared->data='\0';
tHeared->next=NULL;
tHeared->previous=NULL;
return tHeared;
}
void printL(Dnode pH){
Dnode pr=pH->next;
while(pr!=NULL){
printf("%c",pr->data);
pr=pr->next;
}
printf("\r\n");
}
void deleteL(Dnode pH,char pC){
Dnode p,q,r;
p=pH;
while((p->next!=NULL)&&(p->next->data!=pC))
p=p->next;
if(p->next==NULL){
printf("ERROR! 未找到\n");
return;
}
q=p->next;
r=q->next;
p->next=r;
if(r!=NULL){
r->previous=p;
}
free(q);
}
void inserttail(Dnode pH,char pC,int pPos){
Dnode p,q,r;
if(pPos<0){
printf("ERROR!请输入一个大于等于零的数!\n");
}
p=(Dnode)malloc(sizeof(DLnode));
p->data=pC;
p->next=NULL;
p->previous=NULL;
int i; q=pH;
for(i=0;i<pPos;++i){
q=q->next;
if(q==NULL){
printf("ERROR! 超过最大限度!\n");
return;
}
}
r=q->next;
p->next=q->next;
p->previous=q;
q->next=p;
if(r!=NULL){
r->previous=p;
}
}
char get(Dnode pH,int pPos){
if(pPos<0){
printf("ERROR! 请输入一个大于零的数!\n");
return '\0';
} //attention
Dnode p=pH;
int i;
for(i=0;i<pPos;++i){
p=p->next;
if(p==NULL){
printf("ERROR! 超过限度!\n");
return'\0';
}
}
return p->data;
}
Dnode locate(Dnode pH,char pC){
Dnode p=pH;
while((p->next!=NULL)&&(p->next->data!=pC)){
p=p->next;
}
p=p->next;
if(p==NULL){
printf("ERROR! 未找到!\n");
return NULL;
}
return p;
}
void destroy(Dnode pH){
Dnode p=pH;
Dnode q=pH->next;
while(q!=NULL){
free(p);
p=q;
q=q->next;
//printf("YES\n");
}
free(p);
printf("DESTROY END!\n");
}
void printAddress(){
DLnode p,q;
p.data='m';p.next=NULL;p.previous=NULL;
q.data='x';q.next=NULL;q.previous=NULL;
printf("FRIST :%d,%d,%d,%d\n",&p,&p.data,&p.next,&p.previous);
printf("SECOND :%d,%d,%d,%d\n",&q,&q.data,&q.next,&q.previous);
p.next=&q;
}
void Test(){
Dnode t=init();
printf("初始化 :");
printL(t);
printf("尾部添加元素 :");
inserttail(t,'c',0);
inserttail(t,'s',1) ;
inserttail(t,'d',2);
inserttail(t,'n',3);
printL(t);
printf("删除元素 :");
deleteL(t,'s');
deleteL(t,'a');
deleteL(t,'d');
printL(t);
printf("在指定元素后加入 :");
inserttail(t,'w',1);
inserttail(t,'o',2);
inserttail(t,'p',8);
printL(t);
char bb=get(t,2);
printf("GET : %c\n",bb);
char cc=get(t,7);
printf("GET : %c\n",cc);
Dnode tt=locate(t,'b');
printf("LOCATE : %ld\n",tt);
Dnode mm=locate(t,'o');
printf("LOCATE : %ld\n",mm);
destroy(t);
printAddress();
}
void main(){
Test();
}
双向链表弥补了单链表只能从头结点开始访问链表中数据元素的缺陷。可以更为方便地访问链表元素。
预先分配一定的储存空间,用于链表的后续使用。有标识符数组used,反映各结点使用情况。
typedef struct StaticLinkedNode{
char data;
int next;
}*NodePtr;
typedef struct StaticLinkedList{
NodePtr nodes;
int* used;
}*ListPtr;
ListPtr initLinkedList(){
ListPtr tempPtr=(ListPtr)malloc(sizeof(struct StaticLinkedList));
tempPtr->nodes=(NodePtr)malloc(sizeof(struct StaticLinkedNode)*DEFAULT_SIZE);
tempPtr->used=(int*)malloc(sizeof(int)*DEFAULT_SIZE);
tempPtr->nodes[0].data='\0';
tempPtr->nodes[0].next=-1;
tempPtr->used[0]=1;
for(int i=1;i<DEFAULT_SIZE;i++){
tempPtr->used[i]=0;
}
return tempPtr;
}
void printList(ListPtr paraListPtr){
int p=0;
while(p!=-1){
printf("%c",paraListPtr->nodes[p].data);
p=paraListPtr->nodes[p].next;
}
printf("\r\n");
}
void insertElement(ListPtr paraListPtr,char paraChar,int paraPosition){
int p,q,i;
p=0;
for(i=0;i<paraPosition;i++){
p=paraListPtr->nodes[p].next;
if(p==-1){
printf("The position %d is beyond the scope of the list.\r\n",paraPosition);
return;
}
}
for(i=1;i<DEFAULT_SIZE;i++){
if(paraListPtr->used[i]==0){
printf("Space at %d allocated.\r\n",i);
paraListPtr->used[i]=1;
q=i;
break;
}
}
if(i==DEFAULT_SIZE){
printf("No space,\r\n");
return;
}
paraListPtr->nodes[q].data=paraChar;
printf("Linking\r\n");
paraListPtr->nodes[q].next=paraListPtr->nodes[p].next;
paraListPtr->nodes[p].next=q;
}
第二步:Q通过循环,在used数组中找到空闲空间
第三步:将待加入数据加入序号Q(图中为1号)的data区域,并将序号P的next改为Q,used数组中序号Q的值改为1,表示已占用
void deleteElement(ListPtr paraListPtr,char paraChar){
int p,q;
p=0;
while((paraListPtr->nodes[p].next!=-1)&&(paraListPtr->nodes[paraListPtr->nodes[p].next].data!=paraChar)){
p=paraListPtr->nodes[p].next;
}
if(paraListPtr->nodes[p].next==-1){
printf("Cannot delete %c\r\n",paraChar);
return;
}
q=paraListPtr->nodes[p].next;
paraListPtr->nodes[p].next=paraListPtr->nodes[paraListPtr->nodes[p].next].next;
paraListPtr->used[q]=0;
}
第二步:Q"指向"P的next,P的next值改为Q的next值
第三步:将used数组中序号Q的值改为0,表示已释放,再次添加数据至此位置时,覆盖之前的数据即可
void appendInsertDeleteTest(){
ListPtr tempList=initLinkedList();
printList(tempList);
insertElement(tempList,'H',0);
insertElement(tempList,'e',1);
insertElement(tempList,'l',2);
insertElement(tempList,'l',3);
insertElement(tempList,'o',4);
printList(tempList);
printf("Delete 'e'.\r\n");
deleteElement(tempList,'e');
printf("Delete 'a'.\r\n");
deleteElement(tempList,'a');
printf("Delete 'o'.\r\n");
deleteElement(tempList,'o');
printList(tempList);
insertElement(tempList,'x',1);
printList(tempList);
}
1.7运行结果
char get(Slist pH,int pPos){
//pPos是否合法
if(pPos<0){
printf("ERROR! 请输入一个大于零的数!\n");
return '\0';
}
int p=0;
int i;
//通过循环,使p指向相应位置
for(i=0;i<pPos;++i){
p=pH->nodes[p].next;
//若超过链表长度,输出原因,退出程序
if(p==-1){
printf("ERROR! 超过限度!\n");
return'\0';
}
}
//参数合法,返回相应data
return pH->nodes[p].data;
}
int locate(Slist pH,char pC){
int p=0;//p可以理解为类似指针的一个标识符
//通过循环,使p“指向”待查找值
while((pH->nodes[p].next!=-1)&&(pH->nodes[pH->nodes[p].next].data!=pC)){
p=pH->nodes[p].next;
}
p=pH->nodes[p].next;
//若未找到,输出原因并退出
if(p==-1){
printf("ERROR! 未找到!\n");
return 0;
}
//返回结点序号
return p;
}
void Test(){
//初始化
Slist t=init();
printf("初始化 :\n");
printL(t);
//向里添加元素
printf("尾部添加元素 :\n");
inserttail(t,'c',0);
inserttail(t,'s',1) ;
inserttail(t,'d',2);
inserttail(t,'n',3);
printf("TEST %c%c%c%c\n",t->nodes[1].data,t->nodes[2].data,t->nodes[3].data,t->nodes[4].data);
printL(t);
//删除元素测试
printf("删除元素 :\n");
deleteL(t,'s');
deleteL(t,'a');
deleteL(t,'d');
printL(t);
//再次加入元素
printf("在指定元素后加入 :\n");
inserttail(t,'w',1);
inserttail(t,'o',2);
inserttail(t,'p',8);
printL(t);
//GET测试
char bb=get(t,2);
printf("GET : %c\n",bb);
char cc=get(t,7);
printf("GET : %c\n",cc);
//LOCATE测试
int tt=locate(t,'b');
printf("LOCATE : %d\n",tt);
int mm=locate(t,'o');
printf("LOCATE : %d\n",mm);
//printAddress();
}
#include <stdio.h>
#include <malloc.h>
#define DEFAULT_SIZE 5
typedef struct staticLinknode{
char data;
int next;
}*Snode;
typedef struct staticLinklist{
Snode nodes;
int* used;
}*Slist;
Slist init(){
Slist tHeader=(Slist)malloc(sizeof(struct staticLinklist));
tHeader->nodes=(Snode)malloc(sizeof(struct staticLinknode)*DEFAULT_SIZE);
tHeader->used=(int*)malloc(sizeof(int)*DEFAULT_SIZE);
tHeader->nodes[0].data='\0';
tHeader->nodes[0].next=-1;
tHeader->used[0]=1;
for(int i=1;i<DEFAULT_SIZE;i++) {
tHeader->used[i]=0;
}
return tHeader;
}
void printL(Slist pH){
int p=0;
while(p!=-1){
printf("%c",pH->nodes[p].data);
p=pH->nodes[p].next;
}
printf("\r\n");
}
void printLL(Slist pH){
int p=0;
while(p!=-1){
printf("P BEFORE %d\n",p);
printf("%c",pH->nodes[p].data);
p=pH->nodes[p].next;
printf("P AFTER %d\n",p);
}
printf("\r\n");
}
void deleteL(Slist pH,char pC){
int p,q;
p=0;
while((pH->nodes[p].next!=-1)&&(pH->nodes[pH->nodes[p].next].data!=pC)){
p=pH->nodes[p].next;
}
if(pH->nodes[p].next==-1){
printf("ERROR!该元素 %c 不存在! \r\n",pC);
return;
}
q=pH->nodes[p].next;
pH->nodes[p].next=pH->nodes[q].next;
pH->used[q]=0;
}
void inserttail(Slist pH,char pC,int pPos){
int p,q;
if(pPos<0){
printf("ERROR!请输入一个大于等于零的数!\n");
}
p=0;
int i;
for(i=0;i<pPos;++i){
p=pH->nodes[p].next;
if(p==-1){
printf("ERROR!超过最大限度!\n");
return;
}
}
for(i=1;i<DEFAULT_SIZE;++i){
if(pH->used[i]==0){
printf("占用 %d 结点!\n",i);
pH->used[i]=1;
q=i;
break;
}
}
if(i==DEFAULT_SIZE){
printf("ERROR!空间已满!\n");
return;
}
pH->nodes[q].data=pC;
pH->nodes[q].next=pH->nodes[p].next;
pH->nodes[p].next=q;
}
char get(Slist pH,int pPos){
if(pPos<0){
printf("ERROR! 请输入一个大于零的数!\n");
return '\0';
} //attention
int p=0;
int i;
for(i=0;i<pPos;++i){
p=pH->nodes[p].next;
if(p==-1){
printf("ERROR! 超过限度!\n");
return'\0';
}
}
return pH->nodes[p].data;
}
int locate(Slist pH,char pC){
int p=0;
while((pH->nodes[p].next!=-1)&&(pH->nodes[pH->nodes[p].next].data!=pC)){
p=pH->nodes[p].next;
}
p=pH->nodes[p].next;
if(p==-1){
printf("ERROR! 未找到!\n");
return 0;
}
return p;
}
void Test(){
Slist t=init();
printf("初始化 :\n");
printL(t);
printf("尾部添加元素 :\n");
inserttail(t,'c',0);
inserttail(t,'s',1) ;
inserttail(t,'d',2);
inserttail(t,'n',3);
printf("TEST %c%c%c%c\n",t->nodes[1].data,t->nodes[2].data,t->nodes[3].data,t->nodes[4].data);
printL(t);
printf("删除元素 :\n");
deleteL(t,'s');
deleteL(t,'a');
deleteL(t,'d');
printL(t);
printf("在指定元素后加入 :\n");
inserttail(t,'w',1);
inserttail(t,'o',2);
inserttail(t,'p',8);
printL(t);
char bb=get(t,2);
printf("GET : %c\n",bb);
char cc=get(t,7);
printf("GET : %c\n",cc);
int tt=locate(t,'b');
printf("LOCATE : %d\n",tt);
int mm=locate(t,'o');
printf("LOCATE : %d\n",mm);
//printAddress();
}
void main(){
Test();
}
特点:1.在进行插入和删除操作时不需要批量移动元素,只需要修改“指针”,有链式存储结构的特点。
2.分配空间固定,灵活性不高,仅仅适用于事先指定空间的情况。
3.used数组反映各结点的使用情况,查找较为方便。
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- 69lv.com 版权所有 湘ICP备2023021910号-1
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务