1、编程实现单链表删除节点。
解析:如果删除的是头节点,如下图:
则把head指针指向头节点的下一个节点。同时free p1,如下图所示:
如果删除的是中间节点,如下图所示:
则用p2的next指向p1的next同时,free p1 ,如下图所示:
2、编写程序实现单链表的插入。
解析:单链表的插入,如下图所示:
如果插入在头结点以前,则p0的next指向p1,头节点指向p0,如下图所示:
如果插入中间节点,如下图所示:
则先让p2的next指向p0,再让p0指向p1,如下图所示:
如果插入尾节点,如下图所示:
则先让p1的next指向p0,再让p0指向空,如下图所示:
3、编写实现单链表的逆置。
解析:单链表模型如下图所示:
进行单链表逆置,首先要让p2的next指向p1,如下图所示:
再由p1指向p2,p2指向p3,如下图所示:
让后重复p2的next指向p1,p1指向p2,p2指向p3。
1 #include<iostream> 2 using namespace std; 3 typedef struct Student{ 4 int data; 5 struct student *next;//结构体重如果没有用typedef定义结构体,那么想要声明一个结构体的变量,就需要加上struct 6 7 }node; 8 9 node *creat(){ 10 /*① 建立头结点 11 ② 循环输入节点值,0停止输入,其他则继续输入 12 ③ 插入一个值,新建一个节点存储该值,赋值操作,指针修改操作 13 上一个节点的next指向新建立的节点,临时指针指向当前节点方便递增操作 14 ④ 返回一个头结点,该节点不为空 15 */ 16 node *head,*p,*s;//头结点,p临时头节点,s为新建立的节点 17 int x,cycye=1;//输入停止变量 18 head=(node*)malloc(sizeof(node));//建立头结点 19 p=head; 20 while(cycle){ 21 cout<<"请输入链表数据:"<<endl; 22 cin>>x; 23 if(x!=0){//当输入不为0,继续输入 24 s=(node*)malloc(sizeof(node));//S为新建立的节点 25 s->data=x; 26 cout<<s->data<<endl; 27 p->next=s; 28 p=s;//临时指针递增 29 } 30 else{ 31 cycle=0;//停止输入 32 } 33 p->next=NULL;//指针指向链表尾端 34 cout<<" yyy"<<head->next->data<<endl; 35 head=head->next; 36 return (head); 37 } 38 } 39 //打印链表 40 void print(node *head){ 41 /* ① 该链表为空,不输出。 42 ② 该链表不为空且不止一个节点:头结点没有值,则从头结点的下一个节点开始输出 43 */ 44 node *tem_node;//临时节点 45 tem_node=head; 46 //这里还要输出链表长度 47 int length=length(head); 48 cout<<"该链表长度为:"<<length<<endl; 49 50 if(head!=NULL){ 51 tem_node=tem_node->next;//因为该头结点没有值,所以要指向下一个 52 } 53 while(tem_node!=NULL){ 54 cout<<"节点值:"<<tem_node->data<<endl; 55 tem_node=tem_node->next; 56 } 57 } 58 //删除节点 59 node *remove(node *head,int num){ 60 /*① 删除头结点:把头结点的指针指向下一个节点,再把头结点移除 61 ② 删除中间节点:前驱节点的next指向删除节点的next 62 */ 63 node *p1,*p2; 64 p1=head; 65 //找到删除位置 66 while(num!=p1->data &&p1->next!=NULL){//删除的值不为头结点值,并且头结点不为空 67 p2=p1;//删除节点的上一个节点 68 p1=p1->next;//找到删除节点 69 } 70 if(num==p1->data){//如果存在p1节点,删除 71 if(p1==head){//删除头结点 72 head=p1->next; 73 free(p1); 74 } 75 else{ 76 p2->next=p1->next; 77 } 78 } 79 else{ 80 cout<<"不存在值为"<<num<<"的节点!"<<endl; 81 } 82 return (head); 83 } 84 node *insert(node *head,int num){ 85 /*① 从头部插入:头指针指向插入节点,新插入节点next指向原头结点 86 ② 从中间插入:插入位置的前一个节点next指向新插入节点,新插入节点nex指向后一个节点 87 ③ 从尾部插入:和2类似,只是最后是新插入节点next指向NULL 88 */ 89 node *p1,*p2,*p3; 90 p2=head; 91 p1=(node*)malloc(sizeof(node));//新增节点 92 p1->data=num; 93 while(p1->data > p2->data && p2->next!=NULL){//找插入点 94 p3=p2; 95 p2=p2->next; 96 //p2是后一个,P3是前一个 97 } 98 //判断这个插入的位置 99 if(p1->data<=p2->data){ 100 if(head==p2){//从头结点插入 101 p1->next=p2; 102 head=p1; 103 } 104 else {//从中间节点插入 105 p3->next=p1; 106 p1->next=p2; 107 } 108 } 109 else{//没有比他大的数,从尾部插入 110 p2->next=p1; 111 p1->next=NULL; 112 } 113 return (head); 114 } 115 //链表排序 116 node *sort(node *head){ 117 /*冒泡排序法解决*/ 118 node *p,*p2,*p3; 119 int n; 120 int temp; 121 n=length(head); 122 if(head==NULL ||head->next==NULL)//如果只有一个或者没有节点 123 return head; 124 p=head; 125 for(int j=1;j<n;++j) { 126 p=head; 127 for(int i=0;i<n-j;++i) { 128 if(p->data > p->next->data){ 129 temp=p->data; 130 p->data=p->next->data; 131 p->next->data=temp; 132 } 133 p=p->next; 134 } 135 } 136 return (head); 137 138 } 139 //链表的转置 140 node *reverse(node *head){ 141 /**/ 142 node *p1,*p2,*p3; 143 if(head==NULL || head->next==NULL){ 144 return head; 145 } 146 p1=head; 147 p2=p1->next; 148 while(p2){ 149 p3=p2->next; 150 p2->next=p1; 151 p1=p2; 152 p2=p3; 153 } 154 head->nex=NULL; 155 head=p1; 156 return head; 157 } 158 //链表测长 159 int length(node *head){ 160 node *tem_node; 161 tem_node=head; 162 int n=0; 163 while(tem_node!=NULL){ 164 n++; 165 tem_node=tem_node->next; 166 } 167 return n; 168 } 169 170 int main(){ 171 172 }
4、编程实现删除单链表的头元素。
答案:
1 #include<iostream> 2 using namespace std; 3 4 void Removehead(node *head){ 5 node * p=head; 6 head=head->next; 7 free(p); 8 }
5、给出一个单链表,不知道节点N的值,怎么只遍历一次就可以求出中间节点,写出算法。
解析:设立两个指针,比如*p和*q。p每次移动两个位置,即p=p->next->next,q每次移动一个位置,即q=q->next。当p达到最后一个节点时,q就是中间节点了。
答案:
1 #include<iostream> 2 using namespace std; 3 //给出一个单链表,不知道节点N的值,怎么遍历一次就可以求出中间节点 4 void searchMid(node *head,node *mid){ 5 node *p,*q; 6 p=head; 7 q=head; 8 while(p->next->next!=NULL){ 9 p=p->next->next;//p移动两个位置 10 q=q->next;//q移动一个位置,这样相当于p走了两倍,q走了一倍就到达了中点 11 mid=q; 12 } 13 }
6、给定一个单向链表,设计一个时间优化并且空间优化的算法,找出该链表的倒数第m个元素。实现您的算法,注意处理相关的出错情况。m定义为当m=0时,返回链表最后一个元素。
解析:这是一个难题,我们需要的是倒数第m个元素,所以如果我们从某个元素开始,遍历了m个元素之后刚好到达链表末尾,那么这个元素就是要找的元素。也许从链表的尾部倒推回去不是最好的办法,那么我们可以从链表头开始计数。
思路一:我们可以先一次遍历求出链表的总长度n,然后顺序变量求出第n-m个元素,那么这个就是我们要找的元素了。
思路二:我们用两个指针,一个当前位置指针p和一个指向第m个元素的指针q,需要确保两个指针之间相差m个元素,然后以同样的速度移动它们,如果当q到达链表末尾时,那么p指针就是指向倒数第m个元素了。
答案:
1 #include<iostream> 2 using namespace std; 3 //思路二 4 node* search_last_m_num(node *head,int m){ 5 if(head==NULL) 6 return NULL; 7 node *p1,*p2; 8 p1=head; 9 p2=head; 10 while(m){//这样p1和p2相差M个单位长度,当p2走到尽头的时候,p1指向的元素就是倒数第m个元素 11 if(p2->next!=NULL){ 12 p2=p2->next; 13 m--; 14 } 15 else 16 return NULL; 17 } 18 while(p2->next!=NULL){ 19 p1=p1->next; 20 p2=p2->next; 21 } 22 return p1; 23 }