链表用一组任意的存储单元存储线性表的数据元素,每个数据元素ai和指向后继的信息组成的存储映像称为结点,每个结点包含数据域和指针域。
目录
1.老师的代码
1.1 结构体
typedef struct LinkNode{
char data;
struct LinkNode *next;
}LNode,*LinkList,*NodePtr;
1.2初始化
LinkList initLinkList(){
NodePtr tempHeader=(NodePtr)malloc(sizeof(LNode));
tempHeader->data='\0';
tempHeader->next=NULL;
return tempHeader;
}
1.3打印链表
void printList(NodePtr paraHeader){
NodePtr p=paraHeader->next;
while(p!=NULL){
printf("%c",p->data);
p=p->next;
}
printf("\r\n");
}
1.4链表尾部加入元素
void appendElement(NodePtr paraHeader,char paraChar){
NodePtr p,q;
q=(NodePtr)malloc(sizeof(LNode));
q->data=paraChar;
q->next=NULL;
p=paraHeader;
while(p->next!=NULL){
p=p->next;
}
p->next=q;
}
第一步:p指向头结点,q指向待加入结点
第二步:p指向next为NULL的结点
第三步:p指向的结点的next指向q指向的结点,即把p,q分别指向的结点相连
1.5在指定位置后加入元素
void insertElement(NodePtr paraHeader,char paraChar,int paraPosition){
NodePtr p,q;
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.",paraPosition);
return;
}
}
q=(NodePtr)malloc(sizeof(LNode));
q->data=paraChar;
printf("linking\r\n");
q->next=p->next;
p->next=q;
}
第一步:q指向待加入结点,p指向头节点
第二步:通过循环,使p指向指定位置结点
第三步:,待加入结点next指向p后一个结点,p指向的结点的next指向待加入结点
1.6删除结点
void deleteElement(NodePtr paraHeader,char paraChar){
NodePtr p,q;
p=paraHeader;
int i=0;
while((p->next!=NULL)&&(p->next->data!=paraChar)){
//printf("now=%d\n",i);
i++;
//printf("2\n");
p=p->next;
//printf("3\n") ;
}
//printf("4\n");
if(p->next==NULL){
printf("Cannot delete %c\r\n",paraChar);
return;
}
q=p->next;
p->next=p->next->next;
free(q);
}
第一步:p指向头结点
第二步:通过循环,使p指向待删除结点前一个结点,q指向待删除结点
第三步:使p指向的结点的next指向待删除结点后一个结点(这里为NULL),并释放q指向的区域
1.7测试函数
void appendInsertDeleteTest(){
LinkList tempList=initLinkList();
printList(tempList);
appendElement(tempList,'H');
appendElement(tempList,'e');
appendElement(tempList,'l');
appendElement(tempList,'l');
appendElement(tempList,'o');
appendElement(tempList,'!');
printList(tempList);
deleteElement(tempList,'e');
deleteElement(tempList,'a');
deleteElement(tempList,'o');
printList(tempList);
insertElement(tempList,'o',1);
printList(tempList);
}
1.8打印地址函数
void basicAddressTest(){
LNode tempNode1,tempNode2;
tempNode1.data=4;
tempNode1.next=NULL;
tempNode2.data=6;
tempNode2.next=NULL;
printf("The fristnode:%d,%d,%d\r\n",&tempNode1,&tempNode1.data,&tempNode1.next);
printf("The secondnode:%d,%d,%d\r\n",&tempNode2,&tempNode2.data,&tempNode2.next);
tempNode1.next=&tempNode2;
}
1.9运行结果如图
2. 自己的代码
2.1在链表第一个位置加入元素
void appendhead(node pH,char pC){
node p,q;
p=(node)malloc(sizeof(Lnode));
p->data=pC;
p->next=NULL;
q=pH;
p->next=q->next;
q->next=p;
}
第一步:p指向头结点,q指向待加入结点
第二步:使待加入结点的next指向头结点的next
第三步:头结点的next指向待加入结点
2.2按位置查找函数,返回data
char get(node pH,int pPos){
if(pPos<0){
printf("ERROR! 请输入一个大于零的数!\n");
return '\0';
} //判断pPos是否合法
node p=pH;
int i;
//循环至所求位置
for(i=0;i<pPos;++i){
p=p->next;
if(p==NULL){
printf("ERROR! 超过限度!\n"); //超过链表长度,输出原因,退出
return'\0';
}
}
return p->data; //合法,返回data
}
2.3 按值查找函数,返回指针
node locate(node pH,char pC){
node p=pH;
//循环比对元素值
while((p->next!=NULL)&&(p->next->data!=pC)){
p=p->next;
}
p=p->next;
//遍历完整个链表则证明没有找到
if(p==NULL){
printf("ERROR! 未找到!\n");
return NULL; //返回NULL
}
return p;
}
2.4清空链表
void destroy(node pH){
node p=pH;
node q=pH->next;
//循环释放空间
while(q!=NULL){
free(p);
p=q;
q=q->next;
//printf("YES\n");
}
free(p);
printf("DESTROY END!");
}
2.5test函数
void Test(){
Link t=init(); //初始化
printf("初始化 :");
printL(t);
//append函数测试
append(t,'c');
append(t,'s') ;
append(t,'d');
append(t,'n');
printf("尾部添加元素 :");
printL(t);
//delete函数测试
deleteL(t,'s');
deleteL(t,'a'); //测试没有找到的情况
deleteL(t,'d');
printf("删除元素 :");
printL(t);
//inserttail函数测试
inserttail(t,'w',1);
inserttail(t,'o',2);
inserttail(t,'p',8); //超过链表长度测试
printf("在指定元素后加入 :");
printL(t);
//appendhead函数测试
appendhead(t,'b');
appendhead(t,'l');
printf("头插法 :");
printL(t);
//GET测试
char bb=get(t,2);
printf("GET : %c\n",bb);
char cc=get(t,7); //未找到元素的情况
printf("GET : %c\n",cc);
//locate测试
node tt=locate(t,'b');
printf("LOCATE : %ld\n",tt);
node mm=locate(t,'q'); //未找到元素测试
printf("LOCATE : %ld\n",mm);
destroy(t); //释放内存
}
2.6完整代码及运行结果
#include <stdio.h>
#include <malloc.h>
typedef struct Linknode{
char data;
struct Linknode *next;
}Lnode,*Link,*node;
Link init(){
node tHeared=(node)malloc(sizeof(Lnode));
tHeared->data='\0';
tHeared->next=NULL;
return tHeared;
}
void printL(node pH){
node pr=pH->next;
while(pr!=NULL){
printf("%c",pr->data);
pr=pr->next;
}
printf("\r\n");
}
void append(node pH,char pC){
node p,q;
p=(node)malloc(sizeof(Lnode));
p->data=pC;
p->next=NULL;
q=pH;
while(q->next!=NULL)
q=q->next;
q->next=p;
}
void deleteL(node pH,char pC){
node p,q;
p=pH;
while((p->next!=NULL)&&(p->next->data!=pC))
p=p->next;
if(p->next==NULL){
printf("ERROR! 未找到\n");
return;
}
q=p->next;
p->next=p->next->next;
free(q);
}
void inserttail(node pH,char pC,int pPos){
node p,q;
if(pPos<0){
printf("ERROR!请输入一个大于零的数!\n");
}
p=(node)malloc(sizeof(Lnode));
p->data=pC;
p->next=NULL;
int i; q=pH;
for(i=0;i<pPos;++i){
q=q->next;
if(q==NULL){
printf("ERROR! 超过最大限度!\n");
return;
}
}
p->next=q->next;
q->next=p;
}
void appendhead(node pH,char pC){
node p,q;
p=(node)malloc(sizeof(Lnode));
p->data=pC;
p->next=NULL;
q=pH;
p->next=q->next;
q->next=p;
}
char get(node pH,int pPos){
if(pPos<0){
printf("ERROR! 请输入一个大于零的数!\n");
return '\0';
} //判断pPos是否合法
node p=pH;
int i;
//循环至所求位置
for(i=0;i<pPos;++i){
p=p->next;
if(p==NULL){
printf("ERROR! 超过限度!\n"); //超过链表长度,输出原因,退出
return'\0';
}
}
return p->data; //合法,返回data
}
node locate(node pH,char pC){
node p=pH;
//循环比对元素值
while((p->next!=NULL)&&(p->next->data!=pC)){
p=p->next;
}
p=p->next;
//遍历完整个链表则证明没有找到
if(p==NULL){
printf("ERROR! 未找到!\n");
return NULL; //返回NULL
}
return p;
}
void destroy(node pH){
node p=pH;
node q=pH->next;
//循环释放空间
while(q!=NULL){
free(p);
p=q;
q=q->next;
//printf("YES\n");
}
free(p);
printf("DESTROY END!");
}
void Test(){
Link t=init(); //初始化
printf("初始化 :");
printL(t);
//append函数测试
append(t,'c');
append(t,'s') ;
append(t,'d');
append(t,'n');
printf("尾部添加元素 :");
printL(t);
//delete函数测试
deleteL(t,'s');
deleteL(t,'a'); //测试没有找到的情况
deleteL(t,'d');
printf("删除元素 :");
printL(t);
//inserttail函数测试
inserttail(t,'w',1);
inserttail(t,'o',2);
inserttail(t,'p',8); //超过链表长度测试
printf("在指定元素后加入 :");
printL(t);
//appendhead函数测试
appendhead(t,'b');
appendhead(t,'l');
printf("头插法 :");
printL(t);
//GET测试
char bb=get(t,2);
printf("GET : %c\n",bb);
char cc=get(t,7); //未找到元素的情况
printf("GET : %c\n",cc);
//locate测试
node tt=locate(t,'b');
printf("LOCATE : %ld\n",tt);
node mm=locate(t,'q'); //未找到元素测试
printf("LOCATE : %ld\n",mm);
destroy(t); //释放内存
}
void main(){
Test();
}
本地运行结果如图
3.链表和顺序表的比较
链表占用的空间更多,但删减灵活性更强;顺序表在取值操作时效率更高。因此,事先确定大小,频繁取值操作时,因采用顺序表;频繁进行删减操作时,链表更适合。