双链表排序--直接交换指针
/*
* 本文件代码包含对双链表进行排序操作及测试,其中冒泡法,采用值交换排序;选择法,采用节点交换排序
*/
#include <stdio.h>
#include <stdlib.h>
/* 双链表结构体声明,注意链表结点创建参照了《C与指针》一书 */
typedef struct list{
int data;
struct list *forward; /* 指向前向结点 */
struct list *backward; /* 指向后向结点 */
}node;
/* 链表删除 */
void list_free(node *rootp)
{
if(!rootp) {
printf("根节点为空,错误!\n");
return;
}
node *this = rootp->forward;
node *temp;
while(this) {
temp = this;
this = this->forward;
free(temp);
}
free(rootp); /* 最后释放根节点 */
rootp = NULL;
printf("链表删除了!\n");
}
/* 双链表创建,节点数据通过数组赋值 */
node *list_create(int b[], int node_count)
{
int i = 0;
node *rootp;
rootp = (node *)malloc(sizeof(node)); /* 创建根节点 */
if(!rootp) {
printf("Can't create root node!\n");
return NULL;
}
rootp->forward = NULL;
rootp->backward = NULL;
rootp->data = 0;
node *this, *newnode;
newnode = NULL;
this = rootp;
while(node_count-- != 0) {
newnode = (node *)malloc(sizeof(node)); /* 创建新节点 */
if(!newnode) {
printf("Can't create new node!\n");
list_free(rootp);
return NULL;
}
newnode->data = b[i++];
this->forward = newnode;
newnode->backward = this;
this = newnode;
}
newnode->forward = NULL;
rootp->backward = newnode;
rootp->forward->backward = NULL;
return rootp;
}
/* 按后向链表输出 */
void list_print_backward(node *rootp)
{
if(!rootp) {
printf("根节点为空,错误!\n");
return;
}
node *this = rootp->backward;
printf("按后向链表输出\n");
while(this) {
printf("%d ", this->data);
this = this->backward;
}
printf("\n");
}
/* 按前向链表输出 */
void list_print_forward(node *rootp)
{
if(!rootp) {
printf("根节点为空,错误!\n");
return;
}
node *this = rootp->forward;
printf("按前向链表输出\n");
while(this) {
printf("%d ", this->data);
this = this->forward;
}
printf("\n");
}
/* 任意交换两个结点 交换指针 如果看不懂就多画图,多画几遍就行了 */
node *swap_node(node *head, node *this, node *next)
{
node *temp, *temp1;
if(!this->backward && !next->forward) {/* 首和尾巴的交换,需要改变根节点 */
if(this->forward == next) { /* 只有两个结点的情况下 */
//printf("进入!->1\n");
next->forward = this;
next->backward = NULL;
this->backward = next;
this->forward = NULL;
head->forward = next;
head->forward = next;
head->backward = this; /* OK */
} else { /* 有间隔的首尾交换 */
//printf("进入!->2\n");
this->forward->backward = next;
next->backward->forward = this;
next->forward = this->forward;
this->backward = next->backward;
next->backward=this->forward = NULL;
head->forward = next;
head->backward = this; /* OK */
}
} else if(!next->forward) { /* 尾和任意一个交换,需要改变根节点 */
if(this->forward == next) { /* 交换最后两个结点 */
//printf("进入!->3\n");
this->backward->forward = next;
next->backward = this->backward;
next->forward = this;
this->backward = next;
this->forward = NULL;
head->backward = this; /* OK */
} else { /* 和前面其他结点交换 */
//printf("进入!->4\n");
temp = next->backward;
temp->forward = this;
this->backward->forward = next;
this->forward->backward = next;
next->backward = this->backward;
next->forward = this->forward;
this->backward = temp;
this->forward = NULL;
head->backward = this; /* OK */
}
} else if(!this->backward) { /* 头和任意一个交换,需要改变根节点 */
if(this->forward == next) { /* 交换最前面两个结点 */
//printf("进入!->5\n");
next->forward->backward = this;
this->forward = next->forward;
this->backward = next;
next->forward = this;
next->backward = NULL;
head->forward = next; /* OK */
} else { /* 头结点和后面其他结点交换 */
//printf("进入!->6\n");
temp = this->forward;
temp->backward = next;
this->backward = next->backward;
this->forward = next->forward;
next->backward->forward = this;
next->forward->backward = this;
next->forward = temp;
next->backward = NULL; /* OK */
head->forward = next; /* 交换的结点成为头结点 */
}
} else {
/* 当中的任意两个交换 */
if(this->forward == next) { /* 交换连在一起的两个结点 */
//printf("进入!->7\n");
temp1 = this->backward; /* 关键的保存 */
temp = next->forward;
this->backward->forward = next;
next->forward = this;
this->forward = temp;
temp->backward = this;
this->backward = next;
next->backward = temp1; /* OK */
} else { /* 交换隔开的两个结点 */
//printf("进入!->8\n");
temp = this->forward; /* 关键的保存 */
temp1 = this->backward;
this->backward->forward = next;
this->forward->backward = next;
this->backward = next->backward;
this->forward = next->forward;
next->backward->forward = this;
next->forward->backward = this;
next->forward = temp;
next->backward = temp1; /* OK */
}
}
return(head);
}
/* 选择法升序排序,采用结点交换 */
node *list_order_bynode(node *rootp)
{
printf("使用了选择法升序排序!!!!\n");
if(!rootp) {
printf("根节点为空,错误!\n");
return NULL;
}
node *this, *temp, *pi, *pj;
int min_value;
this = rootp->forward;
for(pi = this; pi->forward != NULL; pi = pi->forward) {
min_value = pi->data;
for(pj = pi->forward; pj != NULL; pj = pj->forward) {
if(pj->data < min_value) {
min_value = pj->data;
temp = pj;
}
}
if(min_value != pi->data) {
rootp = swap_node(rootp, pi, temp);
pi = temp;
}
}
return rootp;
}
/* 值交换 */
void swap_value(int *a, int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
/* 冒泡法按升序排序,采用值交换 */
node *list_order_byvalue(node *rootp)
{
printf("使用了冒泡法升序排序!!!!\n");
if(!rootp) {
printf("根节点为空,错误!\n");
return NULL;
}
node *this, *pi, *pj, *temp;
this = rootp->forward;
for(pi = this; pi->forward != NULL; pi = pi->forward) {
for(pj = pi->forward; pj != NULL; pj = pj->forward) {
if(pi->data > pj->data) {
swap_value(&pi->data, &pj->data);
}
}
}
return rootp;
}
/* 测试 */
int main(int argc, char *agrv[])
{
int i;
/* 用于初始化节点数据字段data */
//int b[] = {9, 10, 4, 6, 5, 9, 15, 7, 9, 1, 0, 365, -45, 7899, 654, -45788, 45,1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 45,765451, 7821, 1685, 75218};
int b[] = {1, 4, -3, 2, -5, 16, -7, -10, 9, 8};
//int b[] = {1};
int node_count = sizeof(b) / sizeof(int); /* 节点长度 */
printf("节点长度 = %d\n原始数据:\n", node_count);
for(i = 0; i < node_count; i++) {
printf("%d ", b[i]);
}
printf("\n\n");
node *head = list_create(b, node_count);
head = list_order_bynode(head);
printf("排序后数据:\n");
list_print_forward(head);
printf("\n");
list_print_backward(head);
printf("\n");
node *head1 = list_create(b, node_count);
head1 = list_order_byvalue(head1);
printf("排序后数据:\n");
list_print_forward(head);
printf("\n");
list_print_backward(head);
printf("\n");
list_free(head);
list_free(head1);
//list_print_forward(head);
return 0;
}
代码下载: http://download.csdn.net/detail/conceptcon/5351679
list_head实例:
#define __KERNEL__ //这样才能使用list.h,具体请看list.h
#include "list.h" /*由于我的机器上没有list.h,所以我拷贝了一个,如果你机器上有,应该是加#include <linux/list.h>*/
#include <stdio.h>
#include <string.h>
#define MAX_USER_LEN 32
#define MAX_PAS_LEN 32
#define MAX_SERVER_LEN 1024
typedef struct server_detect_ftp
{
struct list_head list;
char server[MAX_SERVER_LEN];
int port;
char username[MAX_USER_LEN];
char password[MAX_PAS_LEN];
}server_detect_ftp_t;
int main(void)
{
struct list_head head;//头部
server_detect_ftp_t ftp_link;
server_detect_ftp_t ftp_link1;
server_detect_ftp_t *entry;
struct list_head *p;
INIT_LIST_HEAD(&head);//初始化头部
strcpy(ftp_link.server,"www.163.com");
ftp_link.port=34;
strcpy(ftp_link.username,"good");
strcpy(ftp_link.password,"good");
strcpy(ftp_link1.server,"www.163.com");
ftp_link1.port=34;
strcpy(ftp_link1.username,"good");
strcpy(ftp_link1.password,"good");
INIT_LIST_HEAD(&head);
list_add(&ftp_link.list,&head);
list_add(&ftp_link1.list,&head);//添加链表
list_del(&ftp_link1.list);//删除链表
list_for_each(p,&head)//遍历
{
entry=list_entry(p,struct server_detect_ftp,list);//读取某个值
printf("%s\n",entry->username);
}
return 0;
}
指针运算符与优先级
(1)指针运算符* 与取地址运算符&的优先级相同,按自右向左的方向结合。
设有变量定义语句: int a, *p=&a;
则表达式:&*p 的求值顺序为先"*"后"&",即& (*p)=&a=p 。
而表达式:*&a 的求值顺序为先"&"后"*",即* (&a)=*p=a 。
(2)"++"、"--"、"*"、"&"的优先级相同,按自右向左方向结合。下面结合例子加以说明。设有变量定义语句:
int a[4]={100,200,300,400},b;
int * p=&a[0];
为了叙述方便,假设系统给数组a分配的首地址为1000,如图7.4所示。
① b=*p++;
按自右向左结合的原则,表达式 *p++ 求值序顺为先"++"后"*",即:*(p++)。由于"++"在p之后为后置++运算符,所以表达式的实际操作是先取*p值,后进行p++的自加操作。即赋值表达式 b=*p++; 等同于下面两条语句:
b=*p; // b=*p=a[0]=100
p++; //p=p+sizeof(int)= 1004
最后运算的结果为b=100,p=1004指向a[1]。
② b=*++p;
按自右向左结合的原则,表达式 *++p 求值顺序为先"++"后"*",即:*(++p)。由于++在p之前为前置++运算符,所以表达式的实际操作是进行++p的自加操作,后取*p值。即赋值表达式 b=*++p; 等同于下面两条语句:
++p; //p=p+sizeof(int)= 1008,指向a[2]
b=*p; // b=*p=a[2]=300
最后运算的结果为b=300,p=1008指向a[2]。
由于括号内优先运算,所以表达式先取出*p(即a[2])的值并赋给b,然后将*p的值即a[2]内容加1。所以表达式等同于下面两条语句:
b=*p; //b=a[2]=300
a[2]++ ; // a[2]=300+1=301
④ b=*(p++);
由①可知,该表达式等同于*p++,运算结果为:
b=*p; //b=a[2]=301
p++; // p=p+sizeof(int)=1012,指向a[3]
⑤ b=++*p ;
该表达式先进行"*"运算,再进行"++"运算,即先取出*p的值,再将该值加1。因此表达式实际进行了如下运算:b=++(*p)=++a[3]=400+1=401; p仍指向a[3]不变。
将上述讨论中各语句汇总为例题如下:
#include <iostream>
using namespace std;
#include <stdio.h>
#define MIN(A, B) ((A)>=(B)?(B):(A))
void fun()
{
int *p, bb, c;
bb = 25;
p = &c;
c = 20;
printf("MIN(A, B) = %3d\n", MIN(c, bb));
printf("MIN(A, B) = %3d\n", MIN(*p, bb));
printf("MIN(A, B) = %3d\n", MIN(*p++, bb));
printf("MIN(A, B) = %p\n", *p++ >= bb ? bb : *p++);
}
void funcc()
{
int a[4]={100,200,300,400},b;
int *p=&a[0];
cout<<'\t'<<"p="<<p<<endl;
b=*p++;
cout<<"b="<<b<<'\t'<<"p="<<p<<endl;
b=*++p;
cout<<"b="<<b<<'\t'<<"p="<<p<<endl;
b=(*p)++;
cout<<"b="<<b<<'\t'<<"p="<<p<<endl;
b=*(p++);
cout<<"b="<<b<<'\t'<<"p="<<p<<endl;
b=++*p;
cout<<"b="<<b<<'\t'<<"p="<<p<<endl;
}
int main(int argc, char **argv)
{
//无符号数与有符号数相加
unsigned int a = 6;
int b = -12;
if(a+b > 0)
{
printf("dsds\n");
printf("a+b=%d\n" , a+b);
printf("a+b=%p\n" , (void *)(a+b));
}
else
{
printf("ssss\n");
printf("a+b=%d\n" , a+b);
printf("a+b=%p\n" , (void *)(a+b));
}
fun();
funcc();
return 0;
}
运行结果为:
dsds
a+b=-6
a+b=0xfffffffa
MIN(A, B) = 20
MIN(A, B) = 20
MIN(A, B) = 25
MIN(A, B) = 0xbff3cb74
p=0xbff3cb48
b=100 p=0xbff3cb4c
b=300 p=0xbff3cb50
b=300 p=0xbff3cb50
b=301 p=0xbff3cb54
b=401 p=0xbff3cb54