双链表排序--可以在任意位置正确插入节点

双链表排序--直接交换指针

 

/*
 * 本文件代码包含对双链表进行排序操作及测试,其中冒泡法,采用值交换排序;选择法,采用节点交换排序
 */

#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]。

 

        ③ b=(*p)++;
  由于括号内优先运算,所以表达式先取出*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


 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值